@nx/workspace 17.2.4 → 17.2.5

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 CHANGED
@@ -1,4 +1,9 @@
1
- <p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600" alt="Nx - Smart, Fast and Extensible Build System"></p>
1
+ <p style="text-align: center;">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
4
+ <img alt="Nx - Smart Monorepos · Fast CI" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
5
+ </picture>
6
+ </p>
2
7
 
3
8
  <div style="text-align: center;">
4
9
 
@@ -15,9 +20,9 @@
15
20
 
16
21
  <hr>
17
22
 
18
- # Nx: Smart, Fast and Extensible Build System
23
+ # Nx: Smart Monorepos · Fast CI
19
24
 
20
- Nx is a next generation build system with first class monorepo support and powerful integrations.
25
+ Nx is a build system with built-in tooling and advanced CI capabilities. It helps you maintain and scale monorepos, both locally and on CI.
21
26
 
22
27
  ## Getting Started
23
28
 
@@ -57,5 +62,5 @@ npx nx@latest init
57
62
  - [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
58
63
 
59
64
  <p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
60
- width="100%" alt="Nx - Smart, Fast and Extensible Build System"></a></p>
65
+ width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
61
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/workspace",
3
- "version": "17.2.4",
3
+ "version": "v17.2.5",
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": {
@@ -61,13 +61,13 @@
61
61
  }
62
62
  },
63
63
  "dependencies": {
64
- "@nx/devkit": "17.2.4",
64
+ "@nx/devkit": "v17.2.5",
65
65
  "chalk": "^4.1.0",
66
66
  "enquirer": "~2.3.6",
67
67
  "tslib": "^2.3.0",
68
68
  "yargs-parser": "21.1.1",
69
- "nx": "17.2.4",
70
- "@nrwl/workspace": "17.2.4"
69
+ "nx": "v17.2.5",
70
+ "@nrwl/workspace": "v17.2.5"
71
71
  },
72
72
  "publishConfig": {
73
73
  "access": "public"
@@ -11,10 +11,14 @@ async function monorepoGenerator(tree, options) {
11
11
  const projectsToMove = [];
12
12
  // Need to determine libs vs packages directory base on the type of root project.
13
13
  for (const [, project] of projects) {
14
- if (project.root === '.')
14
+ if (project.root === '.') {
15
15
  rootProject = project;
16
- projectsToMove.unshift(project); // move the root project 1st
16
+ }
17
+ else {
18
+ projectsToMove.push(project);
19
+ }
17
20
  }
21
+ projectsToMove.unshift(rootProject); // move the root project 1st
18
22
  // Currently, Nx only handles apps+libs or packages. You cannot mix and match them.
19
23
  // If the standalone project is an app (React, Angular, etc), then use apps+libs.
20
24
  // Otherwise, for TS standalone (lib), use packages.
@@ -5,7 +5,7 @@ const devkit_1 = require("@nx/devkit");
5
5
  function createProjectConfigurationInNewDestination(tree, schema, projectConfig) {
6
6
  projectConfig.name = schema.newProjectName;
7
7
  const isRootProject = projectConfig.root === '.';
8
- // Subtle bug if project name === path, where the updated name was being overrideen.
8
+ // Subtle bug if project name === path, where the updated name was being overridden.
9
9
  const { name, ...rest } = projectConfig;
10
10
  // replace old root path with new one
11
11
  let newProjectString = JSON.stringify(rest);
@@ -17,7 +17,12 @@ function createProjectConfigurationInNewDestination(tree, schema, projectConfig)
17
17
  newProjectString = newProjectString.replace(/"(\.\/)?src\/(.*?)"/g, `"${schema.relativeToRootDestination}/src/$2"`);
18
18
  }
19
19
  else {
20
- newProjectString = newProjectString.replace(new RegExp(projectConfig.root, 'g'), schema.relativeToRootDestination);
20
+ // There's another issue if project name === path, where the target
21
+ // string (my-app:build:production) was being replaced
22
+ // and resulting in my-destination/my-new-name:build:production
23
+ // Change anything but target strings (my-app:build:production).
24
+ // Target string are going to be updated in the updateBuildTargets function
25
+ newProjectString = newProjectString.replace(new RegExp(projectConfig.root + '(?!:)', 'g'), schema.relativeToRootDestination);
21
26
  }
22
27
  const newProject = {
23
28
  name,
@@ -1,4 +1,4 @@
1
1
  import { ProjectConfiguration, Tree } from '@nx/devkit';
2
2
  export declare function maybeExtractTsConfigBase(tree: Tree): void;
3
3
  export declare function maybeExtractJestConfigBase(tree: Tree): Promise<void>;
4
- export declare function maybeExtractEslintConfigIfRootProject(tree: Tree, rootProject: ProjectConfiguration): void;
4
+ export declare function maybeMigrateEslintConfigIfRootProject(tree: Tree, rootProject: ProjectConfiguration): void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.maybeExtractEslintConfigIfRootProject = exports.maybeExtractJestConfigBase = exports.maybeExtractTsConfigBase = void 0;
3
+ exports.maybeMigrateEslintConfigIfRootProject = exports.maybeExtractJestConfigBase = exports.maybeExtractTsConfigBase = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  function maybeExtractTsConfigBase(tree) {
6
6
  let extractTsConfigBase;
@@ -26,11 +26,7 @@ async function maybeExtractJestConfigBase(tree) {
26
26
  await jestInitGenerator(tree, {});
27
27
  }
28
28
  exports.maybeExtractJestConfigBase = maybeExtractJestConfigBase;
29
- function maybeExtractEslintConfigIfRootProject(tree, rootProject) {
30
- if (rootProject.root !== '.')
31
- return;
32
- if (tree.exists('.eslintrc.base.json'))
33
- return;
29
+ function maybeMigrateEslintConfigIfRootProject(tree, rootProject) {
34
30
  let migrateConfigToMonorepoStyle;
35
31
  try {
36
32
  migrateConfigToMonorepoStyle = require('@nx/' +
@@ -39,11 +35,9 @@ function maybeExtractEslintConfigIfRootProject(tree, rootProject) {
39
35
  catch {
40
36
  // eslint not installed
41
37
  }
42
- // Only need to handle migrating the root rootProject.
43
- // If other libs/apps exist, then this migration is already done by `@nx/eslint:lint-rootProject` generator.
44
- migrateConfigToMonorepoStyle?.([rootProject], tree, tree.exists((0, devkit_1.joinPathFragments)(rootProject.root, 'jest.config.ts')) ||
38
+ migrateConfigToMonorepoStyle?.(Array.from((0, devkit_1.getProjects)(tree).values()), tree, tree.exists((0, devkit_1.joinPathFragments)(rootProject.root, 'jest.config.ts')) ||
45
39
  tree.exists((0, devkit_1.joinPathFragments)(rootProject.root, 'jest.config.js'))
46
40
  ? 'jest'
47
41
  : 'none');
48
42
  }
49
- exports.maybeExtractEslintConfigIfRootProject = maybeExtractEslintConfigIfRootProject;
43
+ exports.maybeMigrateEslintConfigIfRootProject = maybeMigrateEslintConfigIfRootProject;
@@ -1,3 +1,3 @@
1
- import { ProjectConfiguration, Tree } from '@nx/devkit';
1
+ import { type ProjectConfiguration, type Tree } from '@nx/devkit';
2
2
  import type { NormalizedSchema, Schema } from '../schema';
3
3
  export declare function normalizeSchema(tree: Tree, schema: Schema, projectConfiguration: ProjectConfiguration): Promise<NormalizedSchema>;
@@ -17,10 +17,16 @@ async function normalizeSchema(tree, schema, projectConfiguration) {
17
17
  }
18
18
  exports.normalizeSchema = normalizeSchema;
19
19
  async function determineProjectNameAndRootOptions(tree, options, projectConfiguration) {
20
+ if (!options.projectNameAndRootFormat &&
21
+ (process.env.NX_INTERACTIVE !== 'true' || !isTTY())) {
22
+ options.projectNameAndRootFormat = 'derived';
23
+ }
20
24
  validateName(options.newProjectName, options.projectNameAndRootFormat, projectConfiguration);
21
25
  const formats = getProjectNameAndRootFormats(tree, options, projectConfiguration);
22
- const format = options.projectNameAndRootFormat ??
23
- (await determineFormat(tree, formats, options));
26
+ const format = options.projectNameAndRootFormat ?? (await determineFormat(formats));
27
+ if (format === 'derived') {
28
+ logDeprecationMessage(formats, options);
29
+ }
24
30
  return formats[format];
25
31
  }
26
32
  function validateName(name, projectNameAndRootFormat, projectConfiguration) {
@@ -55,65 +61,47 @@ function validateName(name, projectNameAndRootFormat, projectConfiguration) {
55
61
  }
56
62
  }
57
63
  }
58
- function getProjectNameAndRootFormats(tree, schema, projectConfiguration) {
59
- let destination = (0, utils_1.normalizePathSlashes)(schema.destination);
60
- const normalizedNewProjectName = schema.newProjectName
61
- ? (0, devkit_1.names)(schema.newProjectName).fileName
62
- : undefined;
63
- const asProvidedProjectName = normalizedNewProjectName ?? schema.projectName;
64
- const asProvidedDestination = destination;
65
- if (normalizedNewProjectName?.startsWith('@')) {
64
+ function getProjectNameAndRootFormats(tree, options, projectConfiguration) {
65
+ let destination = (0, utils_1.normalizePathSlashes)(options.destination);
66
+ if (options.newProjectName &&
67
+ options.newProjectName.includes('/') &&
68
+ !options.newProjectName.startsWith('@')) {
69
+ throw new Error(`You can't specify a new project name with a directory path (${options.newProjectName}). ` +
70
+ `Please provide a valid name without path segments and the full destination with the "--destination" option.`);
71
+ }
72
+ const asProvidedOptions = getAsProvidedOptions(tree, { ...options, destination }, projectConfiguration);
73
+ if (options.projectNameAndRootFormat === 'as-provided') {
66
74
  return {
67
- 'as-provided': {
68
- destination: asProvidedDestination,
69
- importPath: schema.importPath ??
70
- // keep the existing import path if the name didn't change
71
- (normalizedNewProjectName &&
72
- schema.projectName !== normalizedNewProjectName
73
- ? asProvidedProjectName
74
- : undefined),
75
- newProjectName: asProvidedProjectName,
76
- },
75
+ 'as-provided': asProvidedOptions,
76
+ derived: undefined,
77
77
  };
78
78
  }
79
- let npmScope;
80
- let asProvidedImportPath = schema.importPath;
81
- if (!asProvidedImportPath &&
82
- schema.newProjectName &&
83
- projectConfiguration.projectType === 'library') {
84
- npmScope = (0, get_import_path_1.getNpmScope)(tree);
85
- asProvidedImportPath = npmScope
86
- ? `${npmScope === '@' ? '' : '@'}${npmScope}/${asProvidedProjectName}`
87
- : asProvidedProjectName;
88
- }
89
- const derivedProjectName = schema.newProjectName ?? (0, utils_1.getNewProjectName)(destination);
90
- const derivedDestination = (0, utils_1.getDestination)(tree, schema, projectConfiguration);
91
- let derivedImportPath;
92
- if (projectConfiguration.projectType === 'library') {
93
- derivedImportPath =
94
- schema.importPath ??
95
- (0, utils_1.normalizePathSlashes)((0, get_import_path_1.getImportPath)(tree, destination));
79
+ if (asProvidedOptions.newProjectName.startsWith('@')) {
80
+ if (!options.projectNameAndRootFormat) {
81
+ devkit_1.output.warn({
82
+ title: `The provided new project name "${asProvidedOptions.newProjectName}" is a scoped project name and this is not supported by the move generator when using the "derived" format.`,
83
+ bodyLines: [
84
+ `The generator will try to move the project using the "as-provided" format with the new name "${asProvidedOptions.newProjectName}" located at "${asProvidedOptions.destination}".`,
85
+ ],
86
+ });
87
+ return {
88
+ 'as-provided': asProvidedOptions,
89
+ derived: undefined,
90
+ };
91
+ }
92
+ throw new Error(`The provided new project name "${options.newProjectName}" is a scoped project name and this is not supported by the move generator when using the "derived" format. ` +
93
+ `Please provide a name without "@" or use the "as-provided" format.`);
96
94
  }
95
+ const derivedOptions = getDerivedOptions(tree, { ...options, destination }, projectConfiguration);
97
96
  return {
98
- 'as-provided': {
99
- destination: asProvidedDestination,
100
- newProjectName: asProvidedProjectName,
101
- importPath: asProvidedImportPath,
102
- },
103
- derived: {
104
- destination: derivedDestination,
105
- newProjectName: derivedProjectName,
106
- importPath: derivedImportPath,
107
- },
97
+ 'as-provided': asProvidedOptions,
98
+ derived: derivedOptions,
108
99
  };
109
100
  }
110
- async function determineFormat(tree, formats, schema) {
101
+ async function determineFormat(formats) {
111
102
  if (!formats.derived) {
112
103
  return 'as-provided';
113
104
  }
114
- if (process.env.NX_INTERACTIVE !== 'true' || !isTTY()) {
115
- return 'derived';
116
- }
117
105
  const asProvidedDescription = `As provided:
118
106
  Name: ${formats['as-provided'].newProjectName}
119
107
  Destination: ${formats['as-provided'].destination}`;
@@ -138,38 +126,57 @@ async function determineFormat(tree, formats, schema) {
138
126
  ],
139
127
  initial: 'as-provided',
140
128
  }).then(({ format }) => format === asProvidedSelectedValue ? 'as-provided' : 'derived');
129
+ return result;
130
+ }
131
+ function logDeprecationMessage(formats, options) {
141
132
  const callingGenerator = process.env.NX_ANGULAR_MOVE_INVOKED === 'true'
142
133
  ? '@nx/angular:move'
143
134
  : '@nx/workspace:move';
144
- const deprecationWarning = (0, devkit_1.stripIndents) `
135
+ devkit_1.logger.warn((0, devkit_1.stripIndents) `
145
136
  In Nx 18, the project name and destination will no longer be derived.
146
- Please provide the exact new project name and destination in the future.`;
147
- if (result === 'as-provided') {
148
- const { saveDefault } = await (0, enquirer_1.prompt)({
149
- type: 'confirm',
150
- message: `Would you like to configure Nx to always take the project name and destination as provided for ${callingGenerator}?`,
151
- name: 'saveDefault',
152
- initial: true,
153
- });
154
- if (saveDefault) {
155
- const nxJson = (0, devkit_1.readNxJson)(tree);
156
- nxJson.generators ??= {};
157
- nxJson.generators[callingGenerator] ??= {};
158
- nxJson.generators[callingGenerator].projectNameAndRootFormat = result;
159
- (0, devkit_1.updateNxJson)(tree, nxJson);
160
- }
161
- else {
162
- devkit_1.logger.warn(deprecationWarning);
163
- }
137
+ Please provide the exact new project name and destination in the future.
138
+ Example: nx g ${callingGenerator} --projectName ${options.projectName} --destination ${formats['derived'].destination}` +
139
+ (options.projectName !== formats['derived'].newProjectName
140
+ ? ` --newProjectName ${formats['derived'].newProjectName}`
141
+ : ''));
142
+ }
143
+ function getAsProvidedOptions(tree, options, projectConfiguration) {
144
+ const newProjectName = options.newProjectName ?? options.projectName;
145
+ const destination = options.destination;
146
+ if (projectConfiguration.projectType !== 'library') {
147
+ return { destination, newProjectName };
164
148
  }
165
- else {
166
- const example = `Example: nx g ${callingGenerator} --projectName ${schema.projectName} --destination ${formats[result].destination}` +
167
- (schema.projectName !== formats[result].newProjectName
168
- ? ` --newProjectName ${formats[result].newProjectName}`
169
- : '');
170
- devkit_1.logger.warn(deprecationWarning + '\n' + example);
149
+ let importPath = options.importPath;
150
+ if (importPath) {
151
+ return { destination, newProjectName, importPath };
171
152
  }
172
- return result;
153
+ if (options.newProjectName?.startsWith('@')) {
154
+ // keep the existing import path if the name didn't change
155
+ importPath =
156
+ options.newProjectName && options.projectName !== options.newProjectName
157
+ ? newProjectName
158
+ : undefined;
159
+ }
160
+ else if (options.newProjectName) {
161
+ const npmScope = (0, get_import_path_1.getNpmScope)(tree);
162
+ importPath = npmScope
163
+ ? `${npmScope === '@' ? '' : '@'}${npmScope}/${newProjectName}`
164
+ : newProjectName;
165
+ }
166
+ return { destination, newProjectName, importPath };
167
+ }
168
+ function getDerivedOptions(tree, options, projectConfiguration) {
169
+ const newProjectName = options.newProjectName
170
+ ? (0, devkit_1.names)(options.newProjectName).fileName
171
+ : (0, utils_1.getNewProjectName)(options.destination);
172
+ const destination = (0, utils_1.getDestination)(tree, options, projectConfiguration);
173
+ let importPath;
174
+ if (projectConfiguration.projectType === 'library') {
175
+ importPath =
176
+ options.importPath ??
177
+ (0, utils_1.normalizePathSlashes)((0, get_import_path_1.getImportPath)(tree, options.destination));
178
+ }
179
+ return { destination, newProjectName, importPath };
173
180
  }
174
181
  function isTTY() {
175
182
  return !!process.stdout.isTTY && process.env['CI'] !== 'true';
@@ -33,7 +33,6 @@ async function moveGeneratorInternal(tree, rawSchema) {
33
33
  if (projectConfig.root === '.') {
34
34
  (0, extract_base_configs_1.maybeExtractTsConfigBase)(tree);
35
35
  await (0, extract_base_configs_1.maybeExtractJestConfigBase)(tree);
36
- (0, extract_base_configs_1.maybeExtractEslintConfigIfRootProject)(tree, projectConfig);
37
36
  // Reload config since it has been updated after extracting base configs
38
37
  projectConfig = (0, devkit_1.readProjectConfiguration)(tree, rawSchema.projectName);
39
38
  }
@@ -51,6 +50,10 @@ async function moveGeneratorInternal(tree, rawSchema) {
51
50
  (0, update_build_targets_1.updateBuildTargets)(tree, schema);
52
51
  (0, update_default_project_1.updateDefaultProject)(tree, schema);
53
52
  (0, update_implicit_dependencies_1.updateImplicitDependencies)(tree, schema);
53
+ if (projectConfig.root === '.') {
54
+ // we want to migrate eslint config once the root project files are moved
55
+ (0, extract_base_configs_1.maybeMigrateEslintConfigIfRootProject)(tree, projectConfig);
56
+ }
54
57
  await (0, run_angular_plugin_1.runAngularPlugin)(tree, schema);
55
58
  if (!schema.skipFormat) {
56
59
  await (0, devkit_1.formatFiles)(tree);
@@ -2,7 +2,7 @@
2
2
 
3
3
  <a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
4
4
 
5
- ✨ **This workspace has been generated by [Nx, a Smart, fast and extensible build system.](https://nx.dev)** ✨<% if (!!appName) { %>
5
+ ✨ **This workspace has been generated by [Nx, Smart Monorepos · Fast CI.](https://nx.dev)** ✨<% if (!!appName) { %>
6
6
 
7
7
  <% if (includeServe) { %>
8
8
  ## Start the app