@nx/vitest 22.7.0-beta.11 → 22.7.0-beta.13
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/package.json +4 -4
- package/src/plugins/plugin.d.ts.map +1 -1
- package/src/plugins/plugin.js +102 -5
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/vitest",
|
|
3
3
|
"description": "The Nx Plugin for Vitest to enable fast unit testing with Vitest.",
|
|
4
|
-
"version": "22.7.0-beta.
|
|
4
|
+
"version": "22.7.0-beta.13",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"executors": "./executors.json",
|
|
53
53
|
"generators": "./generators.json",
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@nx/devkit": "22.7.0-beta.
|
|
56
|
-
"@nx/js": "22.7.0-beta.
|
|
55
|
+
"@nx/devkit": "22.7.0-beta.13",
|
|
56
|
+
"@nx/js": "22.7.0-beta.13",
|
|
57
57
|
"tslib": "^2.3.0",
|
|
58
58
|
"semver": "^7.6.3",
|
|
59
59
|
"@phenomnomnominal/tsquery": "~6.1.4"
|
|
@@ -71,6 +71,6 @@
|
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"nx": "22.7.0-beta.
|
|
74
|
+
"nx": "22.7.0-beta.13"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAGlB,aAAa,EASd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAGlB,aAAa,EASd,MAAM,YAAY,CAAC;AAepB,MAAM,WAAW,mBAAmB;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CAC5B;AAoBD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,kBAEhC,CAAC;AAIF,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,mBAAmB,CA2F1D,CAAC;AAEF,eAAO,MAAM,aAAa,oCAAc,CAAC"}
|
package/src/plugins/plugin.js
CHANGED
|
@@ -38,6 +38,7 @@ const devkit_1 = require("@nx/devkit");
|
|
|
38
38
|
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
|
39
39
|
const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
|
|
40
40
|
const js_1 = require("@nx/js");
|
|
41
|
+
const internal_1 = require("@nx/js/src/internal");
|
|
41
42
|
const node_fs_1 = require("node:fs");
|
|
42
43
|
const node_path_1 = require("node:path");
|
|
43
44
|
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
|
@@ -80,7 +81,11 @@ exports.createNodes = [
|
|
|
80
81
|
configFiles: [],
|
|
81
82
|
});
|
|
82
83
|
const lockfile = (0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot));
|
|
83
|
-
const
|
|
84
|
+
const tsconfigChainsByProjectRoot = collectTsconfigInputsByProjectRoot(projectRoots, context.workspaceRoot);
|
|
85
|
+
const hashes = await (0, calculate_hash_for_create_nodes_1.calculateHashesForCreateNodes)(projectRoots, normalizedOptions, context, projectRoots.map((root) => [
|
|
86
|
+
lockfile,
|
|
87
|
+
...(tsconfigChainsByProjectRoot.get(root) ?? []),
|
|
88
|
+
]));
|
|
84
89
|
try {
|
|
85
90
|
return await (0, devkit_1.createNodesFromFiles)(async (configFile, _, context, idx) => {
|
|
86
91
|
const projectRoot = (0, node_path_1.dirname)(configFile);
|
|
@@ -90,7 +95,7 @@ exports.createNodes = [
|
|
|
90
95
|
// for different config files.
|
|
91
96
|
const hash = hashes[idx] + configFile;
|
|
92
97
|
const { projectType, metadata, targets } = (targetsCache[hash] ??=
|
|
93
|
-
await buildVitestTargets(configFile, projectRoot, normalizedOptions, context, pmc));
|
|
98
|
+
await buildVitestTargets(configFile, projectRoot, normalizedOptions, context, pmc, tsconfigChainsByProjectRoot.get(projectRoot) ?? []));
|
|
94
99
|
const project = {
|
|
95
100
|
root: projectRoot,
|
|
96
101
|
targets,
|
|
@@ -110,7 +115,7 @@ exports.createNodes = [
|
|
|
110
115
|
},
|
|
111
116
|
];
|
|
112
117
|
exports.createNodesV2 = exports.createNodes;
|
|
113
|
-
async function buildVitestTargets(configFilePath, projectRoot, options, context, pmc) {
|
|
118
|
+
async function buildVitestTargets(configFilePath, projectRoot, options, context, pmc, tsconfigInputs) {
|
|
114
119
|
const absoluteConfigFilePath = (0, devkit_1.joinPathFragments)(context.workspaceRoot, configFilePath);
|
|
115
120
|
// Workaround for the `build$3 is not a function` error that we sometimes see in agents.
|
|
116
121
|
// This should be removed later once we address the issue properly
|
|
@@ -165,7 +170,9 @@ async function buildVitestTargets(configFilePath, projectRoot, options, context,
|
|
|
165
170
|
const targets = {};
|
|
166
171
|
// if file is vitest.config or vite.config has definition for test, create targets for test and/or atomized tests
|
|
167
172
|
if (configFilePath.includes('vitest.config') || hasTest) {
|
|
168
|
-
|
|
173
|
+
const isTypecheckEnabled = !!viteBuildConfig?.test?.typecheck
|
|
174
|
+
?.enabled;
|
|
175
|
+
targets[options.testTargetName] = await testTarget(namedInputs, testOutputs, projectRoot, options.testMode, pmc, isTypecheckEnabled, tsconfigInputs);
|
|
169
176
|
if (options.ciTargetName) {
|
|
170
177
|
const groupName = options.ciGroupName ?? (0, plugins_1.deriveGroupNameFromTarget)(options.ciTargetName);
|
|
171
178
|
const targetGroup = [];
|
|
@@ -240,8 +247,9 @@ async function buildVitestTargets(configFilePath, projectRoot, options, context,
|
|
|
240
247
|
}
|
|
241
248
|
return { targets, metadata, projectType: 'library' };
|
|
242
249
|
}
|
|
243
|
-
async function testTarget(namedInputs, outputs, projectRoot, testMode = 'watch', pmc) {
|
|
250
|
+
async function testTarget(namedInputs, outputs, projectRoot, testMode = 'watch', pmc, isTypecheckEnabled, tsconfigInputs) {
|
|
244
251
|
const command = testMode === 'run' ? 'vitest run' : 'vitest';
|
|
252
|
+
const depOutputsGlob = isTypecheckEnabled ? '**/*.{js,d.ts}' : '**/*.js';
|
|
245
253
|
return {
|
|
246
254
|
command,
|
|
247
255
|
options: { cwd: (0, devkit_1.joinPathFragments)(projectRoot) },
|
|
@@ -250,10 +258,15 @@ async function testTarget(namedInputs, outputs, projectRoot, testMode = 'watch',
|
|
|
250
258
|
...('production' in namedInputs
|
|
251
259
|
? ['default', '^production']
|
|
252
260
|
: ['default', '^default']),
|
|
261
|
+
...tsconfigInputs.map((f) => ({
|
|
262
|
+
json: `{workspaceRoot}/${f}`,
|
|
263
|
+
fields: ['compilerOptions'],
|
|
264
|
+
})),
|
|
253
265
|
{
|
|
254
266
|
externalDependencies: ['vitest'],
|
|
255
267
|
},
|
|
256
268
|
{ env: 'CI' },
|
|
269
|
+
{ dependentTasksOutputFiles: depOutputsGlob, transitive: true },
|
|
257
270
|
],
|
|
258
271
|
outputs,
|
|
259
272
|
metadata: {
|
|
@@ -308,6 +321,90 @@ function normalizeOptions(options) {
|
|
|
308
321
|
options.testMode ??= 'watch';
|
|
309
322
|
return options;
|
|
310
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Collects tsconfig files that Vite's esbuild-based config bundler reads
|
|
326
|
+
* but are outside the project root (and thus not covered by `default`).
|
|
327
|
+
*
|
|
328
|
+
* Vite < 8 uses esbuild's Build API to bundle config files. esbuild walks
|
|
329
|
+
* UP from the entry point, reading and parsing every `tsconfig.json` in
|
|
330
|
+
* every ancestor directory plus their `extends` chains. Vite >= 8 uses
|
|
331
|
+
* rolldown with `tsconfig: false`, but pnpm can resolve different Vite
|
|
332
|
+
* versions per project, so we always collect — the walk is cheap (cached
|
|
333
|
+
* JSON reads) and over-declaring inputs for Vite 8 projects is harmless.
|
|
334
|
+
*
|
|
335
|
+
* Files already handled elsewhere are excluded:
|
|
336
|
+
* - Inside the project root → covered by `default` (`{projectRoot}/**\/*`)
|
|
337
|
+
* - The root tsconfig (tsconfig.base.json or tsconfig.json) → covered by
|
|
338
|
+
* the native TsConfiguration hash instruction
|
|
339
|
+
* - Inside node_modules → invalidated via lockfile
|
|
340
|
+
* - Outside the workspace → cannot be expressed as inputs
|
|
341
|
+
*/
|
|
342
|
+
function collectTsconfigInputsByProjectRoot(projectRoots, workspaceRoot) {
|
|
343
|
+
const jsonCache = new Map();
|
|
344
|
+
const result = new Map();
|
|
345
|
+
const rootTsConfigName = (0, js_1.getRootTsConfigFileName)();
|
|
346
|
+
for (const projectRoot of projectRoots) {
|
|
347
|
+
if (projectRoot === '.')
|
|
348
|
+
continue;
|
|
349
|
+
const outside = [];
|
|
350
|
+
const seen = new Set();
|
|
351
|
+
const projectPrefix = `${projectRoot}/`;
|
|
352
|
+
const collect = (absolutePath) => {
|
|
353
|
+
const wsRelative = (0, node_path_1.relative)(workspaceRoot, absolutePath)
|
|
354
|
+
.split(node_path_1.sep)
|
|
355
|
+
.join('/');
|
|
356
|
+
if (seen.has(wsRelative))
|
|
357
|
+
return;
|
|
358
|
+
seen.add(wsRelative);
|
|
359
|
+
if (wsRelative.startsWith('../') || wsRelative === '..')
|
|
360
|
+
return;
|
|
361
|
+
if (wsRelative.startsWith('node_modules/') ||
|
|
362
|
+
wsRelative.includes('/node_modules/'))
|
|
363
|
+
return;
|
|
364
|
+
if (wsRelative === projectRoot || wsRelative.startsWith(projectPrefix))
|
|
365
|
+
return;
|
|
366
|
+
if (wsRelative === rootTsConfigName)
|
|
367
|
+
return;
|
|
368
|
+
outside.push(wsRelative);
|
|
369
|
+
};
|
|
370
|
+
// 1. Walk the project tsconfig's extends chain
|
|
371
|
+
const projectTsconfig = (0, node_path_1.join)(workspaceRoot, projectRoot, 'tsconfig.json');
|
|
372
|
+
if ((0, node_fs_1.existsSync)(projectTsconfig)) {
|
|
373
|
+
(0, internal_1.walkTsconfigExtendsChain)(projectTsconfig, (absPath) => {
|
|
374
|
+
collect(absPath);
|
|
375
|
+
return 'continue';
|
|
376
|
+
}, { jsonCache });
|
|
377
|
+
}
|
|
378
|
+
// 2. Walk UP ancestor directories (esbuild reads every tsconfig.json
|
|
379
|
+
// between the entry point and the filesystem root)
|
|
380
|
+
let dir = (0, node_path_1.dirname)(projectRoot);
|
|
381
|
+
while (dir && dir !== '.') {
|
|
382
|
+
const ancestorTsconfig = (0, node_path_1.join)(workspaceRoot, dir, 'tsconfig.json');
|
|
383
|
+
if ((0, node_fs_1.existsSync)(ancestorTsconfig)) {
|
|
384
|
+
(0, internal_1.walkTsconfigExtendsChain)(ancestorTsconfig, (absPath) => {
|
|
385
|
+
collect(absPath);
|
|
386
|
+
return 'continue';
|
|
387
|
+
}, { jsonCache });
|
|
388
|
+
}
|
|
389
|
+
const parent = (0, node_path_1.dirname)(dir);
|
|
390
|
+
if (parent === dir)
|
|
391
|
+
break;
|
|
392
|
+
dir = parent;
|
|
393
|
+
}
|
|
394
|
+
// 3. Check the workspace root itself (dirname loop above stops at '.')
|
|
395
|
+
const rootTsconfig = (0, node_path_1.join)(workspaceRoot, 'tsconfig.json');
|
|
396
|
+
if ((0, node_fs_1.existsSync)(rootTsconfig)) {
|
|
397
|
+
(0, internal_1.walkTsconfigExtendsChain)(rootTsconfig, (absPath) => {
|
|
398
|
+
collect(absPath);
|
|
399
|
+
return 'continue';
|
|
400
|
+
}, { jsonCache });
|
|
401
|
+
}
|
|
402
|
+
if (outside.length > 0) {
|
|
403
|
+
result.set(projectRoot, outside);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
311
408
|
function checkIfConfigFileShouldBeProject(projectRoot, context) {
|
|
312
409
|
// Do not create a project if package.json and project.json isn't there.
|
|
313
410
|
const siblingFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot));
|