@nx/workspace 20.4.0-canary.20250123-7524356 → 20.4.0-canary.20250125-15fc599

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/workspace",
3
- "version": "20.4.0-canary.20250123-7524356",
3
+ "version": "20.4.0-canary.20250125-15fc599",
4
4
  "private": false,
5
5
  "description": "The Workspace plugin contains executors and generators that are useful for any Nx workspace. It should be present in every Nx workspace and other plugins build on it.",
6
6
  "repository": {
@@ -38,12 +38,12 @@
38
38
  }
39
39
  },
40
40
  "dependencies": {
41
- "@nx/devkit": "20.4.0-canary.20250123-7524356",
41
+ "@nx/devkit": "20.4.0-canary.20250125-15fc599",
42
42
  "chalk": "^4.1.0",
43
43
  "enquirer": "~2.3.6",
44
44
  "tslib": "^2.3.0",
45
45
  "yargs-parser": "21.1.1",
46
- "nx": "20.4.0-canary.20250123-7524356"
46
+ "nx": "20.4.0-canary.20250125-15fc599"
47
47
  },
48
48
  "publishConfig": {
49
49
  "access": "public"
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.monorepoGenerator = monorepoGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const move_1 = require("../move/move");
6
+ const ts_solution_setup_1 = require("../../utils/ts-solution-setup");
6
7
  async function monorepoGenerator(tree, options) {
7
8
  const projects = (0, devkit_1.getProjects)(tree);
8
9
  const nxJson = (0, devkit_1.readNxJson)(tree);
@@ -22,7 +23,8 @@ async function monorepoGenerator(tree, options) {
22
23
  // Currently, Nx only handles apps+libs or packages. You cannot mix and match them.
23
24
  // If the standalone project is an app (React, Angular, etc), then use apps+libs.
24
25
  // Otherwise, for TS standalone (lib), use packages.
25
- const isRootProjectApp = rootProject.projectType === 'application';
26
+ const isRootProjectApp = (0, ts_solution_setup_1.getProjectType)(tree, rootProject.root, rootProject.projectType) ===
27
+ 'application';
26
28
  const appsDir = isRootProjectApp ? 'apps' : 'packages';
27
29
  const libsDir = isRootProjectApp ? 'libs' : 'packages';
28
30
  if (rootProject) {
@@ -38,13 +40,14 @@ async function monorepoGenerator(tree, options) {
38
40
  });
39
41
  }
40
42
  for (const project of projectsToMove) {
43
+ const projectType = (0, ts_solution_setup_1.getProjectType)(tree, project.root, project.projectType);
41
44
  await (0, move_1.moveGenerator)(tree, {
42
45
  projectName: project.name,
43
46
  newProjectName: project.name,
44
- destination: project.projectType === 'application'
47
+ destination: projectType === 'application'
45
48
  ? (0, devkit_1.joinPathFragments)(appsDir, project.root === '.' ? project.name : project.root)
46
49
  : (0, devkit_1.joinPathFragments)(libsDir, project.root === '.' ? project.name : project.root),
47
- updateImportPath: project.projectType === 'library',
50
+ updateImportPath: projectType === 'library',
48
51
  });
49
52
  }
50
53
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeSchema = normalizeSchema;
4
4
  const get_import_path_1 = require("../../../utilities/get-import-path");
5
5
  const utils_1 = require("./utils");
6
+ const ts_solution_setup_1 = require("../../../utils/ts-solution-setup");
6
7
  async function normalizeSchema(tree, schema, projectConfiguration) {
7
8
  const { destination, newProjectName, importPath } = await determineProjectNameAndRootOptions(tree, schema, projectConfiguration);
8
9
  return {
@@ -14,11 +15,11 @@ async function normalizeSchema(tree, schema, projectConfiguration) {
14
15
  };
15
16
  }
16
17
  async function determineProjectNameAndRootOptions(tree, options, projectConfiguration) {
17
- validateName(options.newProjectName, projectConfiguration);
18
+ validateName(tree, options.newProjectName, projectConfiguration);
18
19
  const projectNameAndRootOptions = getProjectNameAndRootOptions(tree, options, projectConfiguration);
19
20
  return projectNameAndRootOptions;
20
21
  }
21
- function validateName(name, projectConfiguration) {
22
+ function validateName(tree, name, projectConfiguration) {
22
23
  if (!name) {
23
24
  return;
24
25
  }
@@ -34,13 +35,14 @@ function validateName(name, projectConfiguration) {
34
35
  */
35
36
  const libraryPattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
36
37
  const appPattern = '^[a-zA-Z][^:]*$';
37
- if (projectConfiguration.projectType === 'application') {
38
+ const projectType = (0, ts_solution_setup_1.getProjectType)(tree, projectConfiguration.root, projectConfiguration.projectType);
39
+ if (projectType === 'application') {
38
40
  const validationRegex = new RegExp(appPattern);
39
41
  if (!validationRegex.test(name)) {
40
42
  throw new Error(`The new project name should match the pattern "${appPattern}". The provided value "${name}" does not match.`);
41
43
  }
42
44
  }
43
- else if (projectConfiguration.projectType === 'library') {
45
+ else if ((0, ts_solution_setup_1.getProjectType)(tree, projectConfiguration.root, projectConfiguration.projectType) === 'library') {
44
46
  const validationRegex = new RegExp(libraryPattern);
45
47
  if (!validationRegex.test(name)) {
46
48
  throw new Error(`The new project name should match the pattern "${libraryPattern}". The provided value "${name}" does not match.`);
@@ -1,19 +1,3 @@
1
- import { ProjectConfiguration, Tree } from '@nx/devkit';
2
- import { Schema } from '../schema';
3
- /**
4
- * This helper function ensures that we don't move libs or apps
5
- * outside of the folders they should be in.
6
- *
7
- * This will break if someone isn't using the default libs/apps
8
- * folders. In that case, they're on their own :/
9
- */
10
- export declare function getDestination(host: Tree, schema: Schema, project: ProjectConfiguration): string;
11
- /**
12
- * Joins path segments replacing slashes with dashes
13
- *
14
- * @param path
15
- */
16
- export declare function getNewProjectName(path: string): string;
17
1
  /**
18
2
  * Normalizes slashes (removes duplicates)
19
3
  *
@@ -1,38 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getDestination = getDestination;
4
- exports.getNewProjectName = getNewProjectName;
5
3
  exports.normalizePathSlashes = normalizePathSlashes;
6
4
  const devkit_1 = require("@nx/devkit");
7
- /**
8
- * This helper function ensures that we don't move libs or apps
9
- * outside of the folders they should be in.
10
- *
11
- * This will break if someone isn't using the default libs/apps
12
- * folders. In that case, they're on their own :/
13
- */
14
- function getDestination(host, schema, project) {
15
- const projectType = project.projectType;
16
- const workspaceLayout = (0, devkit_1.getWorkspaceLayout)(host);
17
- let rootFolder = workspaceLayout.libsDir;
18
- if (projectType === 'application') {
19
- rootFolder = workspaceLayout.appsDir;
20
- }
21
- return (0, devkit_1.joinPathFragments)(rootFolder, schema.destination);
22
- }
23
- /**
24
- * Joins path segments replacing slashes with dashes
25
- *
26
- * @param path
27
- */
28
- function getNewProjectName(path) {
29
- // strip leading '/' or './' or '../' and trailing '/' and replaces '/' with '-'
30
- return (0, devkit_1.normalizePath)(path)
31
- .replace(/(^\.{0,2}\/|\.{1,2}\/|\/$)/g, '')
32
- .split('/')
33
- .filter((x) => !!x)
34
- .join('-');
35
- }
36
5
  /**
37
6
  * Normalizes slashes (removes duplicates)
38
7
  *
@@ -70,6 +70,9 @@ function generatePreset(host, opts) {
70
70
  : null,
71
71
  parsedArgs.interactive ? '--interactive=true' : '--interactive=false',
72
72
  opts.routing !== undefined ? `--routing=${opts.routing}` : null,
73
+ opts.unitTestRunner !== undefined
74
+ ? `--unitTestRunner=${opts.unitTestRunner}`
75
+ : null,
73
76
  opts.e2eTestRunner !== undefined
74
77
  ? `--e2eTestRunner=${opts.e2eTestRunner}`
75
78
  : null,
@@ -18,6 +18,7 @@ interface Schema {
18
18
  standaloneApi?: boolean;
19
19
  routing?: boolean;
20
20
  packageManager?: PackageManager;
21
+ unitTestRunner?: 'jest' | 'vitest' | 'none';
21
22
  e2eTestRunner?: 'cypress' | 'playwright' | 'detox' | 'jest' | 'none';
22
23
  ssr?: boolean;
23
24
  serverRouting?: boolean;
@@ -73,6 +73,11 @@
73
73
  "type": "boolean",
74
74
  "default": true
75
75
  },
76
+ "unitTestRunner": {
77
+ "description": "The tool to use for running unit tests.",
78
+ "type": "string",
79
+ "enum": ["jest", "vitest", "none"]
80
+ },
76
81
  "e2eTestRunner": {
77
82
  "description": "The tool to use for running e2e tests.",
78
83
  "type": "string",
@@ -30,6 +30,7 @@ async function createPreset(tree, options) {
30
30
  standalone: options.standaloneApi,
31
31
  routing: options.routing,
32
32
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
33
+ unitTestRunner: options.unitTestRunner,
33
34
  bundler: options.bundler,
34
35
  ssr: options.ssr,
35
36
  serverRouting: options.serverRouting,
@@ -48,6 +49,7 @@ async function createPreset(tree, options) {
48
49
  rootProject: true,
49
50
  standalone: options.standaloneApi,
50
51
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
52
+ unitTestRunner: options.unitTestRunner,
51
53
  bundler: options.bundler,
52
54
  ssr: options.ssr,
53
55
  serverRouting: options.serverRouting,
@@ -65,6 +67,8 @@ async function createPreset(tree, options) {
65
67
  linter: options.linter,
66
68
  bundler: options.bundler ?? 'webpack',
67
69
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
70
+ unitTestRunner: options.unitTestRunner ??
71
+ (options.bundler === 'vite' ? 'vitest' : 'jest'),
68
72
  addPlugin,
69
73
  nxCloudToken: options.nxCloudToken,
70
74
  useTsSolution: options.workspaces,
@@ -74,15 +78,16 @@ async function createPreset(tree, options) {
74
78
  else if (options.preset === presets_1.Preset.ReactStandalone) {
75
79
  const { applicationGenerator: reactApplicationGenerator } = require('@nx' +
76
80
  '/react');
81
+ const bundler = options.bundler ?? 'vite';
77
82
  return reactApplicationGenerator(tree, {
78
83
  name: options.name,
79
84
  directory: '.',
80
85
  style: options.style,
81
86
  linter: options.linter,
82
87
  rootProject: true,
83
- bundler: options.bundler ?? 'vite',
88
+ bundler,
84
89
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
85
- unitTestRunner: options.bundler === 'vite' ? 'vitest' : 'jest',
90
+ unitTestRunner: options.unitTestRunner ?? (bundler === 'vite' ? 'vitest' : 'jest'),
86
91
  addPlugin,
87
92
  nxCloudToken: options.nxCloudToken,
88
93
  formatter: options.formatter,
@@ -96,7 +101,7 @@ async function createPreset(tree, options) {
96
101
  directory: (0, path_1.join)('apps', options.name),
97
102
  linter: options.linter,
98
103
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
99
- unitTestRunner: 'vitest',
104
+ unitTestRunner: options.unitTestRunner ?? 'vitest',
100
105
  addPlugin,
101
106
  nxCloudToken: options.nxCloudToken,
102
107
  useTsSolution: options.workspaces,
@@ -112,7 +117,7 @@ async function createPreset(tree, options) {
112
117
  linter: options.linter,
113
118
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
114
119
  rootProject: true,
115
- unitTestRunner: 'vitest',
120
+ unitTestRunner: options.unitTestRunner ?? 'vitest',
116
121
  addPlugin,
117
122
  nxCloudToken: options.nxCloudToken,
118
123
  formatter: options.formatter,
@@ -127,6 +132,7 @@ async function createPreset(tree, options) {
127
132
  style: options.style,
128
133
  linter: options.linter,
129
134
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
135
+ unitTestRunner: options.unitTestRunner,
130
136
  addPlugin,
131
137
  nxCloudToken: options.nxCloudToken,
132
138
  useTsSolution: options.workspaces,
@@ -143,7 +149,7 @@ async function createPreset(tree, options) {
143
149
  linter: options.linter,
144
150
  rootProject: true,
145
151
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
146
- unitTestRunner: 'vitest',
152
+ unitTestRunner: options.unitTestRunner ?? 'vitest',
147
153
  addPlugin,
148
154
  nxCloudToken: options.nxCloudToken,
149
155
  });
@@ -157,6 +163,7 @@ async function createPreset(tree, options) {
157
163
  style: options.style,
158
164
  linter: options.linter,
159
165
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
166
+ unitTestRunner: options.unitTestRunner,
160
167
  addPlugin,
161
168
  nxCloudToken: options.nxCloudToken,
162
169
  useTsSolution: options.workspaces,
@@ -173,7 +180,7 @@ async function createPreset(tree, options) {
173
180
  linter: options.linter,
174
181
  rootProject: true,
175
182
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
176
- unitTestRunner: 'vitest',
183
+ unitTestRunner: options.unitTestRunner ?? 'vitest',
177
184
  addPlugin,
178
185
  nxCloudToken: options.nxCloudToken,
179
186
  });
@@ -189,6 +196,7 @@ async function createPreset(tree, options) {
189
196
  appDir: options.nextAppDir,
190
197
  src: options.nextSrcDir,
191
198
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
199
+ unitTestRunner: options.unitTestRunner,
192
200
  addPlugin,
193
201
  useTsSolution: options.workspaces,
194
202
  formatter: options.formatter,
@@ -205,6 +213,7 @@ async function createPreset(tree, options) {
205
213
  appDir: options.nextAppDir,
206
214
  src: options.nextSrcDir,
207
215
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
216
+ unitTestRunner: options.unitTestRunner,
208
217
  rootProject: true,
209
218
  addPlugin,
210
219
  formatter: options.formatter,
@@ -232,6 +241,7 @@ async function createPreset(tree, options) {
232
241
  directory: (0, path_1.join)('apps', options.name),
233
242
  linter: options.linter,
234
243
  e2eTestRunner: options.e2eTestRunner ?? 'jest',
244
+ unitTestRunner: options.unitTestRunner,
235
245
  addPlugin,
236
246
  useTsSolution: options.workspaces,
237
247
  formatter: options.formatter,
@@ -244,6 +254,7 @@ async function createPreset(tree, options) {
244
254
  directory: (0, path_1.join)('apps', options.name),
245
255
  linter: options.linter,
246
256
  e2eTestRunner: options.e2eTestRunner ?? 'jest',
257
+ unitTestRunner: options.unitTestRunner,
247
258
  addPlugin,
248
259
  useTsSolution: options.workspaces,
249
260
  formatter: options.formatter,
@@ -257,6 +268,7 @@ async function createPreset(tree, options) {
257
268
  directory: (0, path_1.join)('apps', options.name),
258
269
  linter: options.linter,
259
270
  e2eTestRunner: options.e2eTestRunner ?? 'detox',
271
+ unitTestRunner: options.unitTestRunner,
260
272
  addPlugin,
261
273
  nxCloudToken: options.nxCloudToken,
262
274
  bundler: options.bundler ?? 'webpack',
@@ -271,6 +283,7 @@ async function createPreset(tree, options) {
271
283
  directory: (0, path_1.join)('apps', options.name),
272
284
  linter: options.linter,
273
285
  e2eTestRunner: options.e2eTestRunner ?? 'detox',
286
+ unitTestRunner: options.unitTestRunner,
274
287
  addPlugin,
275
288
  nxCloudToken: options.nxCloudToken,
276
289
  useTsSolution: options.workspaces,
@@ -312,6 +325,7 @@ async function createPreset(tree, options) {
312
325
  docker: options.docker,
313
326
  rootProject: true,
314
327
  e2eTestRunner: options.e2eTestRunner ?? 'jest',
328
+ unitTestRunner: options.unitTestRunner,
315
329
  addPlugin,
316
330
  });
317
331
  }
@@ -328,6 +342,7 @@ async function createPreset(tree, options) {
328
342
  docker: options.docker,
329
343
  rootProject: false,
330
344
  e2eTestRunner: options.e2eTestRunner ?? 'jest',
345
+ unitTestRunner: options.unitTestRunner,
331
346
  addPlugin,
332
347
  useTsSolution: options.workspaces,
333
348
  formatter: options.formatter,
@@ -17,6 +17,7 @@ export interface Schema {
17
17
  nextSrcDir?: boolean;
18
18
  routing?: boolean;
19
19
  standaloneApi?: boolean;
20
+ unitTestRunner?: 'jest' | 'vitest' | 'none';
20
21
  e2eTestRunner?: 'cypress' | 'playwright' | 'jest' | 'detox' | 'none';
21
22
  js?: boolean;
22
23
  ssr?: boolean;
@@ -90,6 +90,11 @@
90
90
  "type": "boolean",
91
91
  "default": true
92
92
  },
93
+ "unitTestRunner": {
94
+ "description": "The tool to use for running unit tests.",
95
+ "type": "string",
96
+ "enum": ["jest", "vitest", "none"]
97
+ },
93
98
  "e2eTestRunner": {
94
99
  "description": "The tool to use for running e2e tests.",
95
100
  "type": "string",
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export declare function getProjectType(tree: Tree, projectRoot: string, projectType?: 'library' | 'application'): 'library' | 'application';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getProjectType = getProjectType;
4
+ const devkit_1 = require("@nx/devkit");
5
+ // This is copied from `@nx/js` to avoid circular dependencies.
6
+ function getProjectType(tree, projectRoot, projectType) {
7
+ if (projectType)
8
+ return projectType;
9
+ if ((0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.lib.json'))
10
+ return 'library';
11
+ if ((0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.app.json'))
12
+ return 'application';
13
+ // If there are no exports, assume it is an application since both buildable and non-buildable libraries have exports.
14
+ const packageJsonPath = (0, devkit_1.joinPathFragments)(projectRoot, 'package.json');
15
+ const packageJson = tree.exists(packageJsonPath)
16
+ ? (0, devkit_1.readJson)(tree, (0, devkit_1.joinPathFragments)(projectRoot, 'package.json'))
17
+ : null;
18
+ if (!packageJson?.exports)
19
+ return 'application';
20
+ return 'library';
21
+ }