UNPKG

@nx/vite

Version:

The Nx Plugin for building and testing applications using Vite

97 lines (95 loc) 4.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateLocalVitestConfigs = generateLocalVitestConfigs; const devkit_1 = require("@nx/devkit"); const vitest_config_files_1 = require("./vitest-config-files"); /** * Packages that run vitest through a package.json script but have no local * vite/vitest config relied on Vitest 3 running their own test files from the * package directory. In Vitest 4 the same invocation climbs up to the root * `vitest.config.*`, resolves its `test.projects` globs relative to the * package directory, matches nothing, and hard-errors with "No projects were * found". A minimal local config stops the climb and lets `@nx/vitest` infer * the package's test target. Returns the created file paths. */ function generateLocalVitestConfigs(tree) { const created = []; const packageJsonPaths = []; (0, devkit_1.visitNotIgnoredFiles)(tree, '', (filePath) => { if (filePath === 'package.json' || filePath.endsWith('/package.json')) { packageJsonPaths.push(filePath); } }); const rootHasTsconfig = tree.exists('tsconfig.base.json') || tree.exists('tsconfig.json'); for (const packageJsonPath of packageJsonPaths) { try { processPackage(tree, packageJsonPath, rootHasTsconfig, created); } catch { // Generation is best-effort; a problematic package must not fail the // migration. } } return created.sort(); } function processPackage(tree, packageJsonPath, rootHasTsconfig, created) { let packageJson; try { packageJson = JSON.parse(tree.read(packageJsonPath, 'utf-8')); } catch { return; } const scripts = packageJson?.scripts; if (!scripts || typeof scripts !== 'object') return; if (!Object.values(scripts).some((script) => typeof script === 'string' && scriptInvokesVitest(script))) { return; } const dir = packageJsonPath.includes('/') ? packageJsonPath.slice(0, packageJsonPath.lastIndexOf('/')) : '.'; const siblings = tree.children(dir === '.' ? '' : dir); if (siblings.some((f) => (0, vitest_config_files_1.isVitestConfigFile)(f))) return; // A directory hosting the workspace file is the projects-mode entry // point, both before and after the migration; it needs no local config. if (siblings.some((f) => (0, vitest_config_files_1.isVitestWorkspaceFile)(f))) return; const ext = rootHasTsconfig || siblings.some((f) => /^tsconfig(\..+)?\.json$/.test(f)) ? '.ts' : '.mjs'; const configPath = (0, devkit_1.joinPathFragments)(dir, `vitest.config${ext}`); tree.write(configPath, `import { defineConfig } from 'vitest/config'; export default defineConfig({ test: {}, }); `); created.push(configPath); } /** * True when some command in the script runs the `vitest` binary (directly, * path-prefixed, or after a runner/env prefix like `npx`/`cross-env A=1`) * without pointing it at an explicit config. `npm run vitest` style commands * run another script, not the binary, and invocations passing `--config`, * `-c`, or `--root` don't rely on config discovery from the cwd, so a * generated local config would only get in the way of target inference. */ function scriptInvokesVitest(script) { return script.split(/&&|\|\||;|\|/).some((command) => { const tokens = command.trim().split(/\s+/); const vitestIndex = tokens.findIndex((token, i) => (token === 'vitest' || token.endsWith('/vitest')) && tokens[i - 1] !== 'run' && tokens[i - 1] !== 'run-script'); if (vitestIndex === -1) return false; return !tokens .slice(vitestIndex + 1) .some((token) => token === '--config' || token === '-c' || token === '--root' || token.startsWith('--config=') || token.startsWith('-c=') || token.startsWith('--root=')); }); }