@nx/vitest 0.0.1-alpha.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 (74) hide show
  1. package/LICENSE +22 -0
  2. package/executors.json +10 -0
  3. package/generators.d.ts +4 -0
  4. package/generators.d.ts.map +1 -0
  5. package/generators.js +7 -0
  6. package/generators.json +18 -0
  7. package/index.d.ts +5 -0
  8. package/index.d.ts.map +1 -0
  9. package/index.js +9 -0
  10. package/migrations.json +9 -0
  11. package/package.json +69 -0
  12. package/project.json +52 -0
  13. package/src/executors/test/compat.d.ts +3 -0
  14. package/src/executors/test/compat.d.ts.map +1 -0
  15. package/src/executors/test/compat.js +5 -0
  16. package/src/executors/test/lib/nx-reporter.d.ts +19 -0
  17. package/src/executors/test/lib/nx-reporter.d.ts.map +1 -0
  18. package/src/executors/test/lib/nx-reporter.js +39 -0
  19. package/src/executors/test/lib/utils.d.ts +5 -0
  20. package/src/executors/test/lib/utils.d.ts.map +1 -0
  21. package/src/executors/test/lib/utils.js +68 -0
  22. package/src/executors/test/schema.d.ts +7 -0
  23. package/src/executors/test/schema.json +35 -0
  24. package/src/executors/test/vitest.impl.d.ts +7 -0
  25. package/src/executors/test/vitest.impl.d.ts.map +1 -0
  26. package/src/executors/test/vitest.impl.js +59 -0
  27. package/src/generators/configuration/configuration.d.ts +9 -0
  28. package/src/generators/configuration/configuration.d.ts.map +1 -0
  29. package/src/generators/configuration/configuration.js +284 -0
  30. package/src/generators/configuration/files/tsconfig.spec.json__tmpl__ +22 -0
  31. package/src/generators/configuration/schema.d.ts +16 -0
  32. package/src/generators/configuration/schema.json +65 -0
  33. package/src/generators/init/init.d.ts +8 -0
  34. package/src/generators/init/init.d.ts.map +1 -0
  35. package/src/generators/init/init.js +70 -0
  36. package/src/generators/init/schema.d.ts +11 -0
  37. package/src/generators/init/schema.json +41 -0
  38. package/src/migrations/update-20-3-0/add-vitest-temp-files-to-git-ignore.d.ts +3 -0
  39. package/src/migrations/update-20-3-0/add-vitest-temp-files-to-git-ignore.d.ts.map +1 -0
  40. package/src/migrations/update-20-3-0/add-vitest-temp-files-to-git-ignore.js +17 -0
  41. package/src/plugins/plugin.d.ts +19 -0
  42. package/src/plugins/plugin.d.ts.map +1 -0
  43. package/src/plugins/plugin.js +277 -0
  44. package/src/utils/detect-ui-framework.d.ts +2 -0
  45. package/src/utils/detect-ui-framework.d.ts.map +1 -0
  46. package/src/utils/detect-ui-framework.js +24 -0
  47. package/src/utils/ensure-dependencies.d.ts +9 -0
  48. package/src/utils/ensure-dependencies.d.ts.map +1 -0
  49. package/src/utils/ensure-dependencies.js +47 -0
  50. package/src/utils/executor-utils.d.ts +3 -0
  51. package/src/utils/executor-utils.d.ts.map +1 -0
  52. package/src/utils/executor-utils.js +10 -0
  53. package/src/utils/generator-utils.d.ts +35 -0
  54. package/src/utils/generator-utils.d.ts.map +1 -0
  55. package/src/utils/generator-utils.js +223 -0
  56. package/src/utils/ignore-vitest-temp-files.d.ts +5 -0
  57. package/src/utils/ignore-vitest-temp-files.d.ts.map +1 -0
  58. package/src/utils/ignore-vitest-temp-files.js +54 -0
  59. package/src/utils/options-utils.d.ts +8 -0
  60. package/src/utils/options-utils.d.ts.map +1 -0
  61. package/src/utils/options-utils.js +41 -0
  62. package/src/utils/version-utils.d.ts +16 -0
  63. package/src/utils/version-utils.d.ts.map +1 -0
  64. package/src/utils/version-utils.js +90 -0
  65. package/src/utils/versions.d.ts +23 -0
  66. package/src/utils/versions.d.ts.map +1 -0
  67. package/src/utils/versions.js +26 -0
  68. package/src/utils/vite-config-edit-utils.d.ts +4 -0
  69. package/src/utils/vite-config-edit-utils.d.ts.map +1 -0
  70. package/src/utils/vite-config-edit-utils.js +359 -0
  71. package/tsconfig.json +28 -0
  72. package/tsconfig.lib.json +20 -0
  73. package/tsconfig.lib.tsbuildinfo +1 -0
  74. package/tsconfig.spec.json +24 -0
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodesV2 = exports.createNodes = exports.createDependencies = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
6
+ const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
7
+ const js_1 = require("@nx/js");
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = require("node:path");
10
+ const file_hasher_1 = require("nx/src/hasher/file-hasher");
11
+ const cache_directory_1 = require("nx/src/utils/cache-directory");
12
+ const plugins_1 = require("nx/src/utils/plugins");
13
+ const executor_utils_1 = require("../utils/executor-utils");
14
+ const pmc = (0, devkit_1.getPackageManagerCommand)();
15
+ function readTargetsCache(cachePath) {
16
+ return process.env.NX_CACHE_PROJECT_GRAPH !== 'false' && (0, node_fs_1.existsSync)(cachePath)
17
+ ? (0, devkit_1.readJsonFile)(cachePath)
18
+ : {};
19
+ }
20
+ function writeTargetsToCache(cachePath, results) {
21
+ (0, devkit_1.writeJsonFile)(cachePath, results);
22
+ }
23
+ /**
24
+ * @deprecated The 'createDependencies' function is now a no-op. This functionality is included in 'createNodesV2'.
25
+ */
26
+ const createDependencies = () => {
27
+ return [];
28
+ };
29
+ exports.createDependencies = createDependencies;
30
+ const vitestConfigGlob = '**/{vite,vitest}.config.{js,ts,mjs,mts,cjs,cts}';
31
+ exports.createNodes = [
32
+ vitestConfigGlob,
33
+ async (configFilePaths, options, context) => {
34
+ const optionsHash = (0, file_hasher_1.hashObject)(options);
35
+ const normalizedOptions = normalizeOptions(options);
36
+ const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `vitest-${optionsHash}.hash`);
37
+ const targetsCache = readTargetsCache(cachePath);
38
+ const { roots: projectRoots, configFiles: validConfigFiles } = configFilePaths.reduce((acc, configFile) => {
39
+ const potentialRoot = (0, node_path_1.dirname)(configFile);
40
+ if (checkIfConfigFileShouldBeProject(potentialRoot, context)) {
41
+ acc.roots.push(potentialRoot);
42
+ acc.configFiles.push(configFile);
43
+ }
44
+ return acc;
45
+ }, {
46
+ roots: [],
47
+ configFiles: [],
48
+ });
49
+ const lockfile = (0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot));
50
+ const hashes = await (0, calculate_hash_for_create_nodes_1.calculateHashesForCreateNodes)(projectRoots, normalizedOptions, context, projectRoots.map((r) => [lockfile]));
51
+ try {
52
+ return await (0, devkit_1.createNodesFromFiles)(async (configFile, _, context, idx) => {
53
+ const projectRoot = (0, node_path_1.dirname)(configFile);
54
+ // results from vitest.config.js will be different from results of vite.config.js
55
+ // but the hash will be the same because it is based on the files under the project root.
56
+ // Adding the config file path to the hash ensures that the final hash value is different
57
+ // for different config files.
58
+ const hash = hashes[idx] + configFile;
59
+ const { projectType, metadata, targets } = (targetsCache[hash] ??=
60
+ await buildVitestTargets(configFile, projectRoot, normalizedOptions, context));
61
+ const project = {
62
+ root: projectRoot,
63
+ targets,
64
+ metadata,
65
+ projectType,
66
+ };
67
+ return {
68
+ projects: {
69
+ [projectRoot]: project,
70
+ },
71
+ };
72
+ }, validConfigFiles, options, context);
73
+ }
74
+ finally {
75
+ writeTargetsToCache(cachePath, targetsCache);
76
+ }
77
+ },
78
+ ];
79
+ exports.createNodesV2 = exports.createNodes;
80
+ async function buildVitestTargets(configFilePath, projectRoot, options, context) {
81
+ const absoluteConfigFilePath = (0, devkit_1.joinPathFragments)(context.workspaceRoot, configFilePath);
82
+ // Workaround for the `build$3 is not a function` error that we sometimes see in agents.
83
+ // This should be removed later once we address the issue properly
84
+ try {
85
+ const importEsbuild = () => new Function('return import("esbuild")')();
86
+ await importEsbuild();
87
+ }
88
+ catch {
89
+ // do nothing
90
+ }
91
+ // Workaround for race condition with ESM-only Vite plugins (e.g. @vitejs/plugin-vue@6+)
92
+ // If vite.config.ts is compiled as CJS, then when both require('@vitejs/plugin-vue') and import('@vitejs/plugin-vue')
93
+ // are pending in the same process, Node will throw an error:
94
+ // Error [ERR_INTERNAL_ASSERTION]: Cannot require() ES Module @vitejs/plugin-vue/dist/index.js because it is not yet fully loaded.
95
+ // This may be caused by a race condition if the module is simultaneously dynamically import()-ed via Promise.all().
96
+ try {
97
+ const importVuePlugin = () => new Function('return import("@vitejs/plugin-vue")')();
98
+ await importVuePlugin();
99
+ }
100
+ catch {
101
+ // Plugin not installed or not needed, ignore
102
+ }
103
+ const { resolveConfig } = await (0, executor_utils_1.loadViteDynamicImport)();
104
+ const viteBuildConfig = await resolveConfig({
105
+ configFile: absoluteConfigFilePath,
106
+ mode: 'development',
107
+ }, 'build');
108
+ let metadata = {};
109
+ const { testOutputs, hasTest } = getOutputs(viteBuildConfig, projectRoot, context.workspaceRoot);
110
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
111
+ const targets = {};
112
+ // if file is vitest.config or vite.config has definition for test, create targets for test and/or atomized tests
113
+ if (configFilePath.includes('vitest.config') || hasTest) {
114
+ targets[options.testTargetName] = await testTarget(namedInputs, testOutputs, projectRoot);
115
+ if (options.ciTargetName) {
116
+ const groupName = options.ciGroupName ?? (0, plugins_1.deriveGroupNameFromTarget)(options.ciTargetName);
117
+ const targetGroup = [];
118
+ const dependsOn = [];
119
+ metadata = {
120
+ targetGroups: {
121
+ [groupName]: targetGroup,
122
+ },
123
+ };
124
+ const projectRootRelativeTestPaths = await getTestPathsRelativeToProjectRoot(projectRoot, context.workspaceRoot);
125
+ for (const relativePath of projectRootRelativeTestPaths) {
126
+ if (relativePath.includes('../')) {
127
+ throw new Error('@nx/vitest attempted to run tests outside of the project root. This is not supported and should not happen. Please open an issue at https://github.com/nrwl/nx/issues/new/choose with the following information:\n\n' +
128
+ `\n\n${JSON.stringify({
129
+ projectRoot,
130
+ relativePath,
131
+ projectRootRelativeTestPaths,
132
+ context,
133
+ }, null, 2)}`);
134
+ }
135
+ const targetName = `${options.ciTargetName}--${relativePath}`;
136
+ dependsOn.push(targetName);
137
+ targets[targetName] = {
138
+ // It does not make sense to run atomized tests in watch mode as they are intended to be run in CI
139
+ command: `vitest run ${relativePath}`,
140
+ cache: targets[options.testTargetName].cache,
141
+ inputs: targets[options.testTargetName].inputs,
142
+ outputs: targets[options.testTargetName].outputs,
143
+ options: {
144
+ cwd: projectRoot,
145
+ env: targets[options.testTargetName].options.env,
146
+ },
147
+ metadata: {
148
+ technologies: ['vitest'],
149
+ description: `Run Vitest Tests in ${relativePath}`,
150
+ help: {
151
+ command: `${pmc.exec} vitest --help`,
152
+ example: {
153
+ options: {
154
+ coverage: true,
155
+ },
156
+ },
157
+ },
158
+ },
159
+ };
160
+ targetGroup.push(targetName);
161
+ }
162
+ if (targetGroup.length > 0) {
163
+ targets[options.ciTargetName] = {
164
+ executor: 'nx:noop',
165
+ cache: true,
166
+ inputs: targets[options.testTargetName].inputs,
167
+ outputs: targets[options.testTargetName].outputs,
168
+ dependsOn,
169
+ metadata: {
170
+ technologies: ['vitest'],
171
+ description: 'Run Vitest Tests in CI',
172
+ nonAtomizedTarget: options.testTargetName,
173
+ help: {
174
+ command: `${pmc.exec} vitest --help`,
175
+ example: {
176
+ options: {
177
+ coverage: true,
178
+ },
179
+ },
180
+ },
181
+ },
182
+ };
183
+ targetGroup.unshift(options.ciTargetName);
184
+ }
185
+ }
186
+ }
187
+ return { targets, metadata, projectType: 'library' };
188
+ }
189
+ async function testTarget(namedInputs, outputs, projectRoot) {
190
+ return {
191
+ command: `vitest`,
192
+ options: { cwd: (0, devkit_1.joinPathFragments)(projectRoot) },
193
+ cache: true,
194
+ inputs: [
195
+ ...('production' in namedInputs
196
+ ? ['default', '^production']
197
+ : ['default', '^default']),
198
+ {
199
+ externalDependencies: ['vitest'],
200
+ },
201
+ { env: 'CI' },
202
+ ],
203
+ outputs,
204
+ metadata: {
205
+ technologies: ['vitest'],
206
+ description: `Run Vitest tests`,
207
+ help: {
208
+ command: `${pmc.exec} vitest --help`,
209
+ example: {
210
+ options: {
211
+ bail: 1,
212
+ coverage: true,
213
+ },
214
+ },
215
+ },
216
+ },
217
+ };
218
+ }
219
+ function getOutputs(viteBuildConfig, projectRoot, workspaceRoot) {
220
+ const { test } = viteBuildConfig;
221
+ const reportsDirectoryPath = normalizeOutputPath(test?.coverage?.reportsDirectory, projectRoot, workspaceRoot, 'coverage');
222
+ return {
223
+ testOutputs: [reportsDirectoryPath],
224
+ hasTest: !!test,
225
+ };
226
+ }
227
+ function normalizeOutputPath(outputPath, projectRoot, workspaceRoot, path) {
228
+ if (!outputPath) {
229
+ if (projectRoot === '.') {
230
+ return `{projectRoot}/${path}`;
231
+ }
232
+ else {
233
+ return `{workspaceRoot}/${path}/{projectRoot}`;
234
+ }
235
+ }
236
+ else {
237
+ if ((0, node_path_1.isAbsolute)(outputPath)) {
238
+ return `{workspaceRoot}/${(0, node_path_1.relative)(workspaceRoot, outputPath)}`;
239
+ }
240
+ else {
241
+ if (outputPath.startsWith('..')) {
242
+ return (0, node_path_1.join)('{workspaceRoot}', (0, node_path_1.join)(projectRoot, outputPath));
243
+ }
244
+ else {
245
+ return (0, node_path_1.join)('{projectRoot}', outputPath);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ function normalizeOptions(options) {
251
+ options ??= {};
252
+ options.testTargetName ??= 'test';
253
+ return options;
254
+ }
255
+ function checkIfConfigFileShouldBeProject(projectRoot, context) {
256
+ // Do not create a project if package.json and project.json isn't there.
257
+ const siblingFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot));
258
+ if (!siblingFiles.includes('package.json') &&
259
+ !siblingFiles.includes('project.json')) {
260
+ return false;
261
+ }
262
+ return true;
263
+ }
264
+ async function getTestPathsRelativeToProjectRoot(projectRoot, workspaceRoot) {
265
+ const fullProjectRoot = (0, node_path_1.join)(workspaceRoot, projectRoot);
266
+ const { createVitest } = await Promise.resolve().then(() => require('vitest/node'));
267
+ const vitest = await createVitest('test', {
268
+ root: fullProjectRoot,
269
+ dir: fullProjectRoot,
270
+ filesOnly: true,
271
+ watch: false,
272
+ });
273
+ const relevantTestSpecifications = await vitest.getRelevantTestSpecifications();
274
+ return relevantTestSpecifications
275
+ .filter((ts) => fullProjectRoot === '.' ? true : ts.moduleId.startsWith(fullProjectRoot))
276
+ .map((ts) => (0, node_path_1.relative)(projectRoot, ts.moduleId));
277
+ }
@@ -0,0 +1,2 @@
1
+ export declare function detectUiFramework(project: string): Promise<'angular' | 'react' | 'none'>;
2
+ //# sourceMappingURL=detect-ui-framework.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ui-framework.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/utils/detect-ui-framework.ts"],"names":[],"mappings":"AAMA,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,CAuBvC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectUiFramework = detectUiFramework;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const ANGULAR_NPM_SCOPE = 'angular';
6
+ const ANGULAR_DEPS = ['@nx/angular'];
7
+ const REACT_DEPS = ['react', '@nx/react'];
8
+ async function detectUiFramework(project) {
9
+ const graph = await (0, devkit_1.createProjectGraphAsync)();
10
+ for (const dep of graph.dependencies[project] ?? []) {
11
+ if (dep.source !== project || !dep.target.startsWith('npm:')) {
12
+ continue;
13
+ }
14
+ const npmDependency = dep.target.replace('npm:', '');
15
+ if (dep.target.startsWith(`npm:@${ANGULAR_NPM_SCOPE}/`) ||
16
+ ANGULAR_DEPS.includes(npmDependency)) {
17
+ return 'angular';
18
+ }
19
+ if (REACT_DEPS.includes(npmDependency)) {
20
+ return 'react';
21
+ }
22
+ }
23
+ return 'none';
24
+ }
@@ -0,0 +1,9 @@
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
+ export type EnsureDependenciesOptions = {
3
+ uiFramework: 'angular' | 'react' | 'vue' | 'none';
4
+ compiler?: 'babel' | 'swc';
5
+ includeLib?: boolean;
6
+ testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
7
+ };
8
+ export declare function ensureDependencies(tree: Tree, schema: EnsureDependenciesOptions): Promise<GeneratorCallback>;
9
+ //# sourceMappingURL=ensure-dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-dependencies.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/utils/ensure-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAapB,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;CAC5E,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA6C5B"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureDependencies = ensureDependencies;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const versions_1 = require("./versions");
6
+ const version_utils_1 = require("./version-utils");
7
+ async function ensureDependencies(tree, schema) {
8
+ const useVitestUi = schema.uiFramework === 'angular' ||
9
+ schema.uiFramework === 'react' ||
10
+ schema.uiFramework === 'vue';
11
+ const devDependencies = {};
12
+ if (schema.testEnvironment === 'jsdom') {
13
+ devDependencies['jsdom'] = versions_1.jsdomVersion;
14
+ }
15
+ else if (schema.testEnvironment === 'happy-dom') {
16
+ devDependencies['happy-dom'] = versions_1.happyDomVersion;
17
+ }
18
+ else if (schema.testEnvironment === 'edge-runtime') {
19
+ devDependencies['@edge-runtime/vm'] = versions_1.edgeRuntimeVmVersion;
20
+ }
21
+ else if (schema.testEnvironment !== 'node' && schema.testEnvironment) {
22
+ devkit_1.logger.info(`A custom environment was provided: ${schema.testEnvironment}. You need to install it manually.`);
23
+ }
24
+ if (schema.uiFramework === 'angular') {
25
+ devDependencies['@analogjs/vitest-angular'] = versions_1.analogVitestAngular;
26
+ devDependencies['@analogjs/vite-plugin-angular'] = versions_1.analogVitestAngular;
27
+ }
28
+ if (schema.uiFramework === 'react') {
29
+ if (schema.compiler === 'swc') {
30
+ devDependencies['@vitejs/plugin-react-swc'] = versions_1.vitePluginReactSwcVersion;
31
+ }
32
+ else {
33
+ devDependencies['@vitejs/plugin-react'] = versions_1.vitePluginReactVersion;
34
+ }
35
+ }
36
+ if (schema.includeLib) {
37
+ devDependencies['vite-plugin-dts'] = versions_1.vitePluginDtsVersion;
38
+ if ((0, devkit_1.detectPackageManager)() !== 'pnpm') {
39
+ devDependencies['ajv'] = versions_1.ajvVersion;
40
+ }
41
+ }
42
+ if (useVitestUi) {
43
+ const { vitestUi } = await (0, version_utils_1.getVitestDependenciesVersionsToInstall)(tree);
44
+ devDependencies['@vitest/ui'] = vitestUi;
45
+ }
46
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies);
47
+ }
@@ -0,0 +1,3 @@
1
+ export declare function loadViteDynamicImport(): Promise<typeof import("vite")>;
2
+ export declare function loadVitestDynamicImport(): Promise<typeof import("vitest/node")>;
3
+ //# sourceMappingURL=executor-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor-utils.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/utils/executor-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,IACW,OAAO,CAAC,cAAc,MAAM,CAAC,CAAC,CAC7E;AAED,wBAAgB,uBAAuB,IACgB,OAAO,CAC1D,cAAc,aAAa,CAAC,CAC7B,CACF"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadViteDynamicImport = loadViteDynamicImport;
4
+ exports.loadVitestDynamicImport = loadVitestDynamicImport;
5
+ function loadViteDynamicImport() {
6
+ return Function('return import("vite")')();
7
+ }
8
+ function loadVitestDynamicImport() {
9
+ return Function('return import("vitest/node")')();
10
+ }
@@ -0,0 +1,35 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export type Target = 'build' | 'serve' | 'test' | 'preview';
3
+ export type TargetFlags = Partial<Record<Target, boolean>>;
4
+ export interface VitestGeneratorSchema {
5
+ project: string;
6
+ uiFramework?: 'angular' | 'react' | 'vue' | 'none';
7
+ coverageProvider: 'v8' | 'istanbul' | 'custom';
8
+ inSourceTests?: boolean;
9
+ skipViteConfig?: boolean;
10
+ testTarget?: string;
11
+ skipFormat?: boolean;
12
+ testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
13
+ addPlugin?: boolean;
14
+ runtimeTsconfigFileName?: string;
15
+ compiler?: 'babel' | 'swc';
16
+ projectType?: 'application' | 'library';
17
+ }
18
+ export declare function addOrChangeTestTarget(tree: Tree, options: VitestGeneratorSchema, hasPlugin: boolean): void;
19
+ export interface ViteConfigFileOptions {
20
+ project: string;
21
+ includeLib?: boolean;
22
+ includeVitest?: boolean;
23
+ inSourceTests?: boolean;
24
+ testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
25
+ rollupOptionsExternal?: string[];
26
+ imports?: string[];
27
+ plugins?: string[];
28
+ coverageProvider?: 'v8' | 'istanbul' | 'custom';
29
+ setupFile?: string;
30
+ useEsmExtension?: boolean;
31
+ port?: number;
32
+ previewPort?: number;
33
+ }
34
+ export declare function createOrEditViteConfig(tree: Tree, options: ViteConfigFileOptions, onlyVitest: boolean, projectAlreadyHasViteTargets?: TargetFlags, vitestFileName?: boolean): void;
35
+ //# sourceMappingURL=generator-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator-utils.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/utils/generator-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,IAAI,EAGL,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACnD,gBAAgB,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CACzC;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,OAAO,QAuCnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;IAC3E,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,OAAO,EACnB,4BAA4B,CAAC,EAAE,WAAW,EAC1C,cAAc,CAAC,EAAE,OAAO,QA6LzB"}
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addOrChangeTestTarget = addOrChangeTestTarget;
4
+ exports.createOrEditViteConfig = createOrEditViteConfig;
5
+ const devkit_1 = require("@nx/devkit");
6
+ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
7
+ const vite_config_edit_utils_1 = require("./vite-config-edit-utils");
8
+ const versions_1 = require("./versions");
9
+ function addOrChangeTestTarget(tree, options, hasPlugin) {
10
+ const nxJson = (0, devkit_1.readNxJson)(tree);
11
+ hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
12
+ ? p === '@nx/vitest'
13
+ : p.plugin === '@nx/vitest' || hasPlugin);
14
+ if (hasPlugin) {
15
+ return;
16
+ }
17
+ const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
18
+ const target = options.testTarget ?? 'test';
19
+ const reportsDirectory = (0, devkit_1.joinPathFragments)((0, devkit_1.offsetFromRoot)(project.root), 'coverage', project.root === '.' ? options.project : project.root);
20
+ const testOptions = {
21
+ reportsDirectory,
22
+ };
23
+ project.targets ??= {};
24
+ if (project.targets[target]) {
25
+ throw new Error(`Target "${target}" already exists in the project.`);
26
+ }
27
+ else {
28
+ project.targets[target] = {
29
+ executor: '@nx/vitest:test',
30
+ outputs: ['{options.reportsDirectory}'],
31
+ options: testOptions,
32
+ };
33
+ }
34
+ (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
35
+ }
36
+ function createOrEditViteConfig(tree, options, onlyVitest, projectAlreadyHasViteTargets, vitestFileName) {
37
+ const { root: projectRoot } = (0, devkit_1.readProjectConfiguration)(tree, options.project);
38
+ const extension = options.useEsmExtension ? 'mts' : 'ts';
39
+ const viteConfigPath = vitestFileName
40
+ ? `${projectRoot}/vitest.config.${extension}`
41
+ : `${projectRoot}/vite.config.${extension}`;
42
+ const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
43
+ const buildOutDir = isTsSolutionSetup
44
+ ? './dist'
45
+ : projectRoot === '.'
46
+ ? `./dist/${options.project}`
47
+ : `${(0, devkit_1.offsetFromRoot)(projectRoot)}dist/${projectRoot}`;
48
+ const buildOption = onlyVitest
49
+ ? ''
50
+ : options.includeLib
51
+ ? ` // Configuration for building your library.
52
+ // See: https://vite.dev/guide/build.html#library-mode
53
+ build: {
54
+ outDir: '${buildOutDir}',
55
+ emptyOutDir: true,
56
+ reportCompressedSize: true,
57
+ commonjsOptions: {
58
+ transformMixedEsModules: true,
59
+ },
60
+ lib: {
61
+ // Could also be a dictionary or array of multiple entry points.
62
+ entry: 'src/index.ts',
63
+ name: '${options.project}',
64
+ fileName: 'index',
65
+ // Change this to the formats you want to support.
66
+ // Don't forget to update your package.json as well.
67
+ formats: ['es' as const]
68
+ },
69
+ rollupOptions: {
70
+ // External packages that should not be bundled into your library.
71
+ external: [${options.rollupOptionsExternal ?? ''}]
72
+ },
73
+ },`
74
+ : ` build: {
75
+ outDir: '${buildOutDir}',
76
+ emptyOutDir: true,
77
+ reportCompressedSize: true,
78
+ commonjsOptions: {
79
+ transformMixedEsModules: true,
80
+ },
81
+ },`;
82
+ const imports = options.imports ? [...options.imports] : [];
83
+ const plugins = options.plugins ? [...options.plugins] : [];
84
+ if (!onlyVitest && options.includeLib && !isTsSolutionSetup) {
85
+ imports.push(`import dts from 'vite-plugin-dts'`, `import * as path from 'path'`);
86
+ }
87
+ if (!isTsSolutionSetup) {
88
+ imports.push(`import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'`, `import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'`);
89
+ plugins.push(`nxViteTsPaths()`, `nxCopyAssetsPlugin(['*.md'])`);
90
+ (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@nx/vite': versions_1.nxVersion });
91
+ }
92
+ if (!onlyVitest && options.includeLib) {
93
+ plugins.push(`dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json')${!isTsSolutionSetup ? ', pathsToAliases: false' : ''} })`);
94
+ }
95
+ const reportsDirectory = isTsSolutionSetup
96
+ ? './test-output/vitest/coverage'
97
+ : projectRoot === '.'
98
+ ? `./coverage/${options.project}`
99
+ : `${(0, devkit_1.offsetFromRoot)(projectRoot)}coverage/${projectRoot}`;
100
+ const testOption = options.includeVitest
101
+ ? ` test: {
102
+ name: '${options.project}',
103
+ watch: false,
104
+ globals: true,
105
+ environment: '${options.testEnvironment ?? 'jsdom'}',
106
+ include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
107
+ ${options.setupFile ? ` setupFiles: ['${options.setupFile}'],\n` : ''}\
108
+ ${options.inSourceTests
109
+ ? ` includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],\n`
110
+ : ''}\
111
+ reporters: ['default'],
112
+ coverage: {
113
+ reportsDirectory: '${reportsDirectory}',
114
+ provider: ${options.coverageProvider
115
+ ? `'${options.coverageProvider}' as const`
116
+ : `'v8' as const`},
117
+ }
118
+ },`
119
+ : '';
120
+ const defineOption = options.inSourceTests
121
+ ? ` define: {
122
+ 'import.meta.vitest': undefined
123
+ },`
124
+ : '';
125
+ const devServerOption = onlyVitest
126
+ ? ''
127
+ : options.includeLib
128
+ ? ''
129
+ : ` server:{
130
+ port: ${options.port ?? 4200},
131
+ host: 'localhost',
132
+ },`;
133
+ const previewServerOption = onlyVitest
134
+ ? ''
135
+ : options.includeLib
136
+ ? ''
137
+ : ` preview:{
138
+ port: ${options.previewPort ?? 4300},
139
+ host: 'localhost',
140
+ },`;
141
+ const workerOption = isTsSolutionSetup
142
+ ? ` // Uncomment this if you are using workers.
143
+ // worker: {
144
+ // plugins: [],
145
+ // },`
146
+ : ` // Uncomment this if you are using workers.
147
+ // worker: {
148
+ // plugins: [ nxViteTsPaths() ],
149
+ // },`;
150
+ const cacheDir = `cacheDir: '${normalizedJoinPaths((0, devkit_1.offsetFromRoot)(projectRoot), 'node_modules', '.vite', projectRoot === '.' ? options.project : projectRoot)}',`;
151
+ if (tree.exists(viteConfigPath)) {
152
+ handleViteConfigFileExists(tree, viteConfigPath, options, buildOption, buildOutDir, imports, plugins, testOption, reportsDirectory, cacheDir, projectRoot, (0, devkit_1.offsetFromRoot)(projectRoot), projectAlreadyHasViteTargets);
153
+ return;
154
+ }
155
+ const viteConfigContent = `/// <reference types='vitest' />
156
+ import { defineConfig } from 'vite';
157
+ ${imports.join(';\n')}${imports.length ? ';' : ''}
158
+
159
+ export default defineConfig(() => ({
160
+ root: __dirname,
161
+ ${printOptions(cacheDir, devServerOption, previewServerOption, ` plugins: [${plugins.join(', ')}],`, workerOption, buildOption, defineOption, testOption)}
162
+ }));
163
+ `.replace(/\s+(?=(\n|$))/gm, '\n');
164
+ tree.write(viteConfigPath, viteConfigContent);
165
+ }
166
+ function printOptions(...options) {
167
+ return options.filter(Boolean).join('\n');
168
+ }
169
+ function handleViteConfigFileExists(tree, viteConfigPath, options, buildOption, buildOutDir, imports, plugins, testOption, reportsDirectory, cacheDir, projectRoot, offsetFromRoot, projectAlreadyHasViteTargets) {
170
+ if (projectAlreadyHasViteTargets?.build &&
171
+ projectAlreadyHasViteTargets?.test) {
172
+ return;
173
+ }
174
+ if (process.env.NX_VERBOSE_LOGGING === 'true') {
175
+ devkit_1.logger.info(`vite.config.ts already exists for project ${options.project}.`);
176
+ }
177
+ const buildOptionObject = options.includeLib
178
+ ? {
179
+ lib: {
180
+ entry: 'src/index.ts',
181
+ name: options.project,
182
+ fileName: 'index',
183
+ formats: ['es'],
184
+ },
185
+ rollupOptions: {
186
+ external: options.rollupOptionsExternal ?? [],
187
+ },
188
+ outDir: buildOutDir,
189
+ reportCompressedSize: true,
190
+ commonjsOptions: {
191
+ transformMixedEsModules: true,
192
+ },
193
+ }
194
+ : {
195
+ outDir: buildOutDir,
196
+ reportCompressedSize: true,
197
+ commonjsOptions: {
198
+ transformMixedEsModules: true,
199
+ },
200
+ };
201
+ const testOptionObject = {
202
+ globals: true,
203
+ environment: options.testEnvironment ?? 'jsdom',
204
+ include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
205
+ reporters: ['default'],
206
+ coverage: {
207
+ reportsDirectory: reportsDirectory,
208
+ provider: `'${options.coverageProvider ?? 'v8'}'`,
209
+ },
210
+ };
211
+ const changed = (0, vite_config_edit_utils_1.ensureViteConfigIsCorrect)(tree, viteConfigPath, buildOption, buildOptionObject, imports, plugins, testOption, testOptionObject, cacheDir, projectAlreadyHasViteTargets ?? {});
212
+ if (!changed) {
213
+ devkit_1.logger.warn(`Make sure the following setting exists in your Vite configuration file (${viteConfigPath}):
214
+
215
+ ${buildOption}
216
+
217
+ `);
218
+ }
219
+ }
220
+ function normalizedJoinPaths(...paths) {
221
+ const path = (0, devkit_1.joinPathFragments)(...paths);
222
+ return path.startsWith('.') ? path : `./${path}`;
223
+ }
@@ -0,0 +1,5 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export declare function ignoreVitestTempFiles(tree: Tree, projectRoot?: string | undefined): Promise<void>;
3
+ export declare function addVitestTempFilesToGitIgnore(tree: Tree): void;
4
+ export declare function isEslintInstalled(tree: Tree): boolean;
5
+ //# sourceMappingURL=ignore-vitest-temp-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore-vitest-temp-files.d.ts","sourceRoot":"","sources":["../../../../../packages/vitest/src/utils/ignore-vitest-temp-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAG9E,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAU9D;AAiCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAYrD"}