@nx/devkit 0.0.0-pr-31222-862e973 → 0.0.0-pr-31313-387cdca

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 (32) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/migrations.json +1 -14
  4. package/package.json +5 -6
  5. package/src/executors/parse-target-string.d.ts +0 -4
  6. package/src/executors/read-target-options.js +3 -3
  7. package/src/generators/artifact-name-and-directory-utils.d.ts +23 -18
  8. package/src/generators/artifact-name-and-directory-utils.js +79 -205
  9. package/src/generators/format-files.d.ts +7 -1
  10. package/src/generators/format-files.js +17 -2
  11. package/src/generators/project-name-and-root-utils.d.ts +11 -16
  12. package/src/generators/project-name-and-root-utils.js +68 -230
  13. package/src/generators/prompt.d.ts +2 -0
  14. package/src/generators/prompt.js +14 -0
  15. package/src/generators/target-defaults-utils.js +1 -1
  16. package/src/generators/update-ts-configs-to-js.js +17 -22
  17. package/src/tasks/install-packages-task.js +1 -1
  18. package/src/utils/add-plugin.js +20 -8
  19. package/src/utils/async-iterable/create-async-iterable.d.ts +1 -0
  20. package/src/utils/async-iterable/create-async-iterable.js +10 -0
  21. package/src/utils/binary-extensions.js +1 -0
  22. package/src/utils/calculate-hash-for-create-nodes.d.ts +1 -0
  23. package/src/utils/calculate-hash-for-create-nodes.js +13 -0
  24. package/src/utils/config-utils.js +61 -33
  25. package/src/utils/package-json.js +12 -8
  26. package/src/utils/replace-package.js +1 -0
  27. package/src/utils/versions.d.ts +1 -1
  28. package/src/utils/versions.js +1 -1
  29. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +0 -2
  30. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +0 -9
  31. package/src/migrations/update-16-9-0/migrate-mf-util-usage.d.ts +0 -3
  32. package/src/migrations/update-16-9-0/migrate-mf-util-usage.js +0 -200
@@ -1,157 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.determineProjectNameAndRootOptions = determineProjectNameAndRootOptions;
4
- exports.setCwd = setCwd;
4
+ exports.resolveImportPath = resolveImportPath;
5
+ exports.ensureRootProjectName = ensureRootProjectName;
5
6
  const enquirer_1 = require("enquirer");
6
- const path_1 = require("path");
7
- const get_workspace_layout_1 = require("../utils/get-workspace-layout");
8
- const names_1 = require("../utils/names");
9
7
  const devkit_exports_1 = require("nx/src/devkit-exports");
8
+ const path_1 = require("path");
10
9
  async function determineProjectNameAndRootOptions(tree, options) {
11
- if (!options.projectNameAndRootFormat &&
12
- (process.env.NX_INTERACTIVE !== 'true' || !isTTY())) {
13
- options.projectNameAndRootFormat = 'derived';
14
- }
15
- validateName(options.name, options.projectNameAndRootFormat);
16
- const formats = getProjectNameAndRootFormats(tree, options);
17
- const format = options.projectNameAndRootFormat ?? (await determineFormat(formats));
18
- if (format === 'derived' && options.callingGenerator) {
19
- logDeprecationMessage(options.callingGenerator, formats);
20
- }
21
- return {
22
- ...formats[format],
23
- projectNameAndRootFormat: format,
24
- };
25
- }
26
- function validateName(name, projectNameAndRootFormat) {
27
- if (projectNameAndRootFormat === 'derived' && name.startsWith('@')) {
28
- throw new Error(`The project name "${name}" cannot start with "@" when the "projectNameAndRootFormat" is "derived".`);
29
- }
30
- /**
31
- * Matches two types of project names:
32
- *
33
- * 1. Valid npm package names (e.g., '@scope/name' or 'name').
34
- * 2. Names starting with a letter and can contain any character except whitespace and ':'.
35
- *
36
- * The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
37
- * that it doesn't allow the ":" character. It was wrong to allow it because it would
38
- * conflict with the notation for tasks.
39
- */
40
- const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
41
- const validationRegex = new RegExp(pattern);
42
- if (!validationRegex.test(name)) {
43
- throw new Error(`The project name should match the pattern "${pattern}". The provided value "${name}" does not match.`);
44
- }
45
- }
46
- function logDeprecationMessage(callingGenerator, formats) {
47
- devkit_exports_1.logger.warn((0, devkit_exports_1.stripIndents) `
48
- In Nx 20, generating projects will no longer derive the name and root.
49
- Please provide the exact project name and root in the future.
50
- Example: nx g ${callingGenerator} ${formats['derived'].projectName} --directory ${formats['derived'].projectRoot}
51
- `);
52
- }
53
- async function determineFormat(formats) {
54
- if (!formats.derived) {
55
- return 'as-provided';
56
- }
57
- const asProvidedDescription = `As provided:
58
- Name: ${formats['as-provided'].projectName}
59
- Root: ${formats['as-provided'].projectRoot}`;
60
- const asProvidedSelectedValue = `${formats['as-provided'].projectName} @ ${formats['as-provided'].projectRoot}`;
61
- const derivedDescription = `Derived:
62
- Name: ${formats['derived'].projectName}
63
- Root: ${formats['derived'].projectRoot}`;
64
- const derivedSelectedValue = `${formats['derived'].projectName} @ ${formats['derived'].projectRoot}`;
65
- if (asProvidedSelectedValue === derivedSelectedValue) {
66
- return 'as-provided';
67
- }
68
- const result = await (0, enquirer_1.prompt)({
69
- type: 'select',
70
- name: 'format',
71
- message: 'What should be the project name and where should it be generated?',
72
- choices: [
73
- {
74
- message: asProvidedDescription,
75
- name: asProvidedSelectedValue,
76
- },
77
- {
78
- message: derivedDescription,
79
- name: derivedSelectedValue,
80
- },
81
- ],
82
- initial: 0,
83
- }).then(({ format }) => format === asProvidedSelectedValue ? 'as-provided' : 'derived');
84
- return result;
85
- }
86
- function getProjectNameAndRootFormats(tree, options) {
87
- const directory = options.directory
88
- ? (0, devkit_exports_1.normalizePath)(options.directory.replace(/^\.?\//, ''))
89
- : undefined;
90
- const { name: asProvidedParsedName, directory: asProvidedParsedDirectory } = parseNameForAsProvided(options.name);
91
- if (asProvidedParsedDirectory && directory) {
92
- throw new Error(`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
93
- `Please specify either a directory or a name with a directory path.`);
94
- }
95
- const asProvidedOptions = getAsProvidedOptions(tree, {
96
- ...options,
97
- directory: directory ?? asProvidedParsedDirectory,
98
- name: asProvidedParsedName,
99
- });
100
- if (options.projectNameAndRootFormat === 'as-provided') {
101
- return {
102
- 'as-provided': asProvidedOptions,
103
- derived: undefined,
104
- };
105
- }
106
- if (asProvidedOptions.projectName.startsWith('@')) {
107
- if (!options.projectNameAndRootFormat) {
108
- devkit_exports_1.output.warn({
109
- title: `The provided name "${options.name}" contains a scoped project name and this is not supported by the "${options.callingGenerator}" when using the "derived" format.`,
110
- bodyLines: [
111
- `The generator will try to generate the project "${asProvidedOptions.projectName}" using the "as-provided" format at "${asProvidedOptions.projectRoot}".`,
112
- ],
113
- });
114
- return {
115
- 'as-provided': asProvidedOptions,
116
- derived: undefined,
117
- };
118
- }
119
- throw new Error(`The provided name "${options.name}" contains a scoped project name and this is not supported by the "${options.callingGenerator}" when using the "derived" format. ` +
120
- `Please provide a name without "@" or use the "as-provided" format.`);
121
- }
122
- const { name: derivedParsedName, directory: derivedParsedDirectory } = parseNameForDerived(options.name);
123
- const derivedOptions = getDerivedOptions(tree, {
124
- ...options,
125
- directory: directory ?? derivedParsedDirectory,
126
- name: derivedParsedName,
127
- });
128
- return {
129
- 'as-provided': asProvidedOptions,
130
- derived: derivedOptions,
131
- };
132
- }
133
- function getAsProvidedOptions(tree, options) {
10
+ // root projects must provide name option
11
+ if (options.directory === '.' && !options.name) {
12
+ throw new Error(`When generating a root project, you must also specify the name option.`);
13
+ }
14
+ const directory = (0, devkit_exports_1.normalizePath)(options.directory);
15
+ const name = options.name ??
16
+ directory.match(/(@[^@/]+(\/[^@/]+)+)/)?.[1] ??
17
+ directory.substring(directory.lastIndexOf('/') + 1);
18
+ validateOptions(options.name, name, options.directory);
134
19
  let projectSimpleName;
135
20
  let projectFileName;
136
- if (options.name.startsWith('@')) {
137
- const [_scope, ...rest] = options.name.split('/');
21
+ if (name.startsWith('@')) {
22
+ const [_scope, ...rest] = name.split('/');
138
23
  projectFileName = rest.join('-');
139
24
  projectSimpleName = rest.pop();
140
25
  }
141
26
  else {
142
- projectSimpleName = options.name;
143
- projectFileName = options.name;
27
+ projectSimpleName = name;
28
+ projectFileName = name;
144
29
  }
145
30
  let projectRoot;
146
31
  const relativeCwd = getRelativeCwd();
147
- if (options.directory) {
32
+ if (directory) {
148
33
  // append the directory to the current working directory if it doesn't start with it
149
- if (options.directory === relativeCwd ||
150
- options.directory.startsWith(`${relativeCwd}/`)) {
151
- projectRoot = options.directory;
34
+ if (directory === relativeCwd || directory.startsWith(`${relativeCwd}/`)) {
35
+ projectRoot = directory;
152
36
  }
153
37
  else {
154
- projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, options.directory);
38
+ projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, directory);
155
39
  }
156
40
  }
157
41
  else if (options.rootProject) {
@@ -160,29 +44,16 @@ function getAsProvidedOptions(tree, options) {
160
44
  else {
161
45
  projectRoot = relativeCwd;
162
46
  // append the project name to the current working directory if it doesn't end with it
163
- if (!relativeCwd.endsWith(options.name)) {
164
- projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, options.name);
47
+ if (!relativeCwd.endsWith(name)) {
48
+ projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, name);
165
49
  }
166
50
  }
167
- let importPath = undefined;
168
- if (options.projectType === 'library') {
169
- importPath = options.importPath;
170
- if (!importPath) {
171
- if (options.name.startsWith('@')) {
172
- importPath = options.name;
173
- }
174
- else {
175
- const npmScope = getNpmScope(tree);
176
- importPath =
177
- projectRoot === '.'
178
- ? (0, devkit_exports_1.readJson)(tree, 'package.json').name ??
179
- getImportPath(npmScope, options.name)
180
- : getImportPath(npmScope, options.name);
181
- }
182
- }
51
+ if (projectRoot.startsWith('..')) {
52
+ throw new Error(`The resolved project root "${projectRoot}" is outside of the workspace root "${devkit_exports_1.workspaceRoot}".`);
183
53
  }
54
+ const importPath = options.importPath ?? resolveImportPath(tree, name, projectRoot);
184
55
  return {
185
- projectName: options.name,
56
+ projectName: name,
186
57
  names: {
187
58
  projectSimpleName,
188
59
  projectFileName,
@@ -191,53 +62,52 @@ function getAsProvidedOptions(tree, options) {
191
62
  projectRoot,
192
63
  };
193
64
  }
194
- function getDerivedOptions(tree, options) {
195
- const name = (0, names_1.names)(options.name).fileName;
196
- let { projectDirectory, layoutDirectory } = getDirectories(tree, options.directory, options.projectType);
197
- const projectDirectoryWithoutLayout = projectDirectory
198
- ? `${(0, names_1.names)(projectDirectory).fileName}/${name}`
199
- : options.rootProject
200
- ? '.'
201
- : name;
202
- // the project name uses the directory without the layout directory
203
- const projectName = projectDirectoryWithoutLayout === '.'
204
- ? name
205
- : projectDirectoryWithoutLayout.replace(/\//g, '-');
206
- const projectSimpleName = name;
207
- let projectRoot = projectDirectoryWithoutLayout;
208
- if (projectDirectoryWithoutLayout !== '.') {
209
- // prepend the layout directory
210
- projectRoot = (0, devkit_exports_1.joinPathFragments)(layoutDirectory, projectRoot);
211
- }
65
+ function resolveImportPath(tree, projectName, projectRoot) {
212
66
  let importPath;
213
- if (options.projectType === 'library') {
214
- importPath = options.importPath;
215
- if (!importPath) {
216
- const npmScope = getNpmScope(tree);
217
- importPath =
218
- projectRoot === '.'
219
- ? (0, devkit_exports_1.readJson)(tree, 'package.json').name ??
220
- getImportPath(npmScope, projectName)
221
- : getImportPath(npmScope, projectDirectoryWithoutLayout);
67
+ if (projectName.startsWith('@')) {
68
+ importPath = projectName;
69
+ }
70
+ else {
71
+ const npmScope = getNpmScope(tree);
72
+ importPath =
73
+ projectRoot === '.'
74
+ ? (0, devkit_exports_1.readJson)(tree, 'package.json').name ??
75
+ getImportPath(npmScope, projectName)
76
+ : getImportPath(npmScope, projectName);
77
+ }
78
+ return importPath;
79
+ }
80
+ async function ensureRootProjectName(options, projectType) {
81
+ if (!options.name && options.directory === '.' && getRelativeCwd() === '') {
82
+ const result = await (0, enquirer_1.prompt)({
83
+ type: 'input',
84
+ name: 'name',
85
+ message: `What do you want to name the ${projectType}?`,
86
+ });
87
+ options.name = result.name;
88
+ }
89
+ }
90
+ function validateOptions(providedName, derivedName, directory) {
91
+ /**
92
+ * The provided name and the derived name from the provided directory must match one of two cases:
93
+ *
94
+ * 1. Valid npm package names (e.g., '@scope/name' or 'name').
95
+ * 2. Names starting with a letter and can contain any character except whitespace and ':'.
96
+ *
97
+ * The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
98
+ * that it doesn't allow the ":" character. It was wrong to allow it because it would
99
+ * conflict with the notation for tasks.
100
+ */
101
+ const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
102
+ const validationRegex = new RegExp(pattern);
103
+ if (providedName) {
104
+ if (!validationRegex.test(providedName)) {
105
+ throw new Error(`The name should match the pattern "${pattern}". The provided value "${providedName}" does not match.`);
222
106
  }
223
107
  }
224
- return {
225
- projectName,
226
- names: {
227
- projectSimpleName,
228
- projectFileName: projectName,
229
- },
230
- importPath,
231
- projectRoot,
232
- };
233
- }
234
- function getDirectories(tree, directory, projectType) {
235
- let { projectDirectory, layoutDirectory } = (0, get_workspace_layout_1.extractLayoutDirectory)(directory);
236
- if (!layoutDirectory) {
237
- const { appsDir, libsDir } = (0, get_workspace_layout_1.getWorkspaceLayout)(tree);
238
- layoutDirectory = projectType === 'application' ? appsDir : libsDir;
108
+ else if (!validationRegex.test(derivedName)) {
109
+ throw new Error(`The derived name from the provided directory should match the pattern "${pattern}". The derived name "${derivedName}" from the provided value "${directory}" does not match.`);
239
110
  }
240
- return { projectDirectory, layoutDirectory };
241
111
  }
242
112
  function getImportPath(npmScope, name) {
243
113
  return npmScope ? `${npmScope === '@' ? '' : '@'}${npmScope}/${name}` : name;
@@ -248,9 +118,6 @@ function getNpmScope(tree) {
248
118
  : { name: null };
249
119
  return name?.startsWith('@') ? name.split('/')[0].substring(1) : undefined;
250
120
  }
251
- function isTTY() {
252
- return !!process.stdout.isTTY && process.env['CI'] !== 'true';
253
- }
254
121
  /**
255
122
  * When running a script with the package manager (e.g. `npm run`), the package manager will
256
123
  * traverse the directory tree upwards until it finds a `package.json` and will set `process.cwd()`
@@ -265,32 +132,3 @@ function getCwd() {
265
132
  function getRelativeCwd() {
266
133
  return (0, devkit_exports_1.normalizePath)((0, path_1.relative)(devkit_exports_1.workspaceRoot, getCwd())).replace(/\/$/, '');
267
134
  }
268
- /**
269
- * Function for setting cwd during testing
270
- */
271
- function setCwd(path) {
272
- process.env.INIT_CWD = (0, path_1.join)(devkit_exports_1.workspaceRoot, path);
273
- }
274
- function parseNameForAsProvided(rawName) {
275
- const directory = (0, devkit_exports_1.normalizePath)(rawName);
276
- if (rawName.includes('@')) {
277
- const index = directory.lastIndexOf('@');
278
- if (index === 0) {
279
- return { name: rawName, directory: undefined };
280
- }
281
- const name = directory.substring(index);
282
- return { name, directory };
283
- }
284
- if (rawName.includes('/')) {
285
- const index = directory.lastIndexOf('/');
286
- const name = directory.substring(index + 1);
287
- return { name, directory };
288
- }
289
- return { name: rawName, directory: undefined };
290
- }
291
- function parseNameForDerived(rawName) {
292
- const parsedName = (0, devkit_exports_1.normalizePath)(rawName).split('/');
293
- const name = parsedName.pop();
294
- const directory = parsedName.length ? parsedName.join('/') : undefined;
295
- return { name, directory };
296
- }
@@ -0,0 +1,2 @@
1
+ import { prompt } from 'enquirer';
2
+ export declare function promptWhenInteractive<T>(questions: Parameters<typeof prompt>[0], defaultValue: T): Promise<T>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promptWhenInteractive = promptWhenInteractive;
4
+ const enquirer_1 = require("enquirer");
5
+ const devkit_internals_1 = require("nx/src/devkit-internals");
6
+ async function promptWhenInteractive(questions, defaultValue) {
7
+ if (!isInteractive()) {
8
+ return defaultValue;
9
+ }
10
+ return await (0, enquirer_1.prompt)(questions);
11
+ }
12
+ function isInteractive() {
13
+ return (!(0, devkit_internals_1.isCI)() && !!process.stdout.isTTY && process.env.NX_INTERACTIVE === 'true');
14
+ }
@@ -46,7 +46,7 @@ async function addE2eCiTargetDefaults(tree, e2ePlugin, buildTarget, pathToE2ECon
46
46
  const ciTargetName = typeof foundPluginForApplication === 'string'
47
47
  ? 'e2e-ci'
48
48
  : foundPluginForApplication.options?.ciTargetName ?? 'e2e-ci';
49
- const ciTargetNameGlob = `${ciTargetName}--**/*`;
49
+ const ciTargetNameGlob = `${ciTargetName}--**/**`;
50
50
  nxJson.targetDefaults ??= {};
51
51
  const e2eCiTargetDefaults = nxJson.targetDefaults[ciTargetNameGlob];
52
52
  if (!e2eCiTargetDefaults) {
@@ -3,21 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateTsConfigsToJs = updateTsConfigsToJs;
4
4
  const devkit_exports_1 = require("nx/src/devkit-exports");
5
5
  function updateTsConfigsToJs(tree, options) {
6
- let updateConfigPath;
6
+ let updateConfigPath = null;
7
7
  const paths = {
8
8
  tsConfig: `${options.projectRoot}/tsconfig.json`,
9
9
  tsConfigLib: `${options.projectRoot}/tsconfig.lib.json`,
10
10
  tsConfigApp: `${options.projectRoot}/tsconfig.app.json`,
11
11
  };
12
- const getProjectType = (tree) => {
13
- if (tree.exists(paths.tsConfigApp)) {
14
- return 'application';
15
- }
16
- if (tree.exists(paths.tsConfigLib)) {
17
- return 'library';
18
- }
19
- throw new Error(`project is missing tsconfig.lib.json or tsconfig.app.json`);
20
- };
21
12
  (0, devkit_exports_1.updateJson)(tree, paths.tsConfig, (json) => {
22
13
  if (json.compilerOptions) {
23
14
  json.compilerOptions.allowJs = true;
@@ -27,21 +18,25 @@ function updateTsConfigsToJs(tree, options) {
27
18
  }
28
19
  return json;
29
20
  });
30
- const projectType = getProjectType(tree);
31
- if (projectType === 'library') {
21
+ if (tree.exists(paths.tsConfigLib)) {
32
22
  updateConfigPath = paths.tsConfigLib;
33
23
  }
34
- if (projectType === 'application') {
24
+ if (tree.exists(paths.tsConfigApp)) {
35
25
  updateConfigPath = paths.tsConfigApp;
36
26
  }
37
- (0, devkit_exports_1.updateJson)(tree, updateConfigPath, (json) => {
38
- json.include = uniq([...json.include, 'src/**/*.js']);
39
- json.exclude = uniq([
40
- ...json.exclude,
41
- 'src/**/*.spec.js',
42
- 'src/**/*.test.js',
43
- ]);
44
- return json;
45
- });
27
+ if (updateConfigPath) {
28
+ (0, devkit_exports_1.updateJson)(tree, updateConfigPath, (json) => {
29
+ json.include = uniq([...(json.include ?? []), 'src/**/*.js']);
30
+ json.exclude = uniq([
31
+ ...(json.exclude ?? []),
32
+ 'src/**/*.spec.js',
33
+ 'src/**/*.test.js',
34
+ ]);
35
+ return json;
36
+ });
37
+ }
38
+ else {
39
+ throw new Error(`project is missing tsconfig.lib.json or tsconfig.app.json`);
40
+ }
46
41
  }
47
42
  const uniq = (value) => [...new Set(value)];
@@ -27,7 +27,7 @@ function installPackagesTask(tree, alwaysRun = false, cwd = '', packageManager =
27
27
  const execSyncOptions = {
28
28
  cwd: (0, path_1.join)(tree.root, cwd),
29
29
  stdio: process.env.NX_GENERATE_QUIET === 'true' ? 'ignore' : 'inherit',
30
- windowsHide: true,
30
+ windowsHide: false,
31
31
  };
32
32
  // ensure local registry from process is not interfering with the install
33
33
  // when we start the process from temp folder the local registry would override the custom registry
@@ -55,8 +55,12 @@ async function _addPluginInternal(tree, graph, pluginName, pluginFactory, option
55
55
  }
56
56
  catch (e) {
57
57
  // Errors are okay for this because we're only running 1 plugin
58
- if (e instanceof devkit_internals_1.ProjectConfigurationsError) {
58
+ if ((0, devkit_internals_1.isProjectConfigurationsError)(e)) {
59
59
  projConfigs = e.partialProjectConfigurationsResult;
60
+ // ignore errors from projects with no name
61
+ if (!e.errors.every(devkit_internals_1.isProjectsWithNoNameError)) {
62
+ throw e;
63
+ }
60
64
  }
61
65
  else {
62
66
  throw e;
@@ -89,8 +93,12 @@ async function _addPluginInternal(tree, graph, pluginName, pluginFactory, option
89
93
  }
90
94
  catch (e) {
91
95
  // Errors are okay for this because we're only running 1 plugin
92
- if (e instanceof devkit_internals_1.ProjectConfigurationsError) {
96
+ if ((0, devkit_internals_1.isProjectConfigurationsError)(e)) {
93
97
  projConfigs = e.partialProjectConfigurationsResult;
98
+ // ignore errors from projects with no name
99
+ if (!e.errors.every(devkit_internals_1.isProjectsWithNoNameError)) {
100
+ throw e;
101
+ }
94
102
  }
95
103
  else {
96
104
  throw e;
@@ -129,7 +137,8 @@ function processProject(tree, projectRoot, projectConfiguration) {
129
137
  if (!targetCommands.length) {
130
138
  return;
131
139
  }
132
- const replacedTargets = new Set();
140
+ let hasChanges = false;
141
+ targetCommands.sort((a, b) => b.command.split(/\s/).length - a.command.split(/\s/).length);
133
142
  for (const targetCommand of targetCommands) {
134
143
  const { command, target, configuration } = targetCommand;
135
144
  const targetCommandRegex = new RegExp(`(?<=^|&)((?: )*(?:[^&\\r\\n\\s]+ )*)(${command})((?: [^&\\r\\n\\s]+)*(?: )*)(?=$|&)`, 'g');
@@ -140,7 +149,7 @@ function processProject(tree, projectRoot, projectConfiguration) {
140
149
  packageJson.scripts[scriptName] = script.replace(targetCommandRegex, configuration
141
150
  ? `$1nx ${target} --configuration=${configuration}$3`
142
151
  : `$1nx ${target}$3`);
143
- replacedTargets.add(target);
152
+ hasChanges = true;
144
153
  }
145
154
  else {
146
155
  /**
@@ -196,23 +205,26 @@ function processProject(tree, projectRoot, projectConfiguration) {
196
205
  }
197
206
  if (!hasArgsWithDifferentValues && !scriptHasExtraArgs) {
198
207
  // they are the same, replace with the command removing the args
199
- packageJson.scripts[scriptName] = packageJson.scripts[scriptName].replace(match, match.replace(commandRegex, configuration
208
+ const script = packageJson.scripts[scriptName];
209
+ packageJson.scripts[scriptName] = script.replace(match, match.replace(commandRegex, configuration
200
210
  ? `$1nx ${target} --configuration=${configuration}$4`
201
211
  : `$1nx ${target}$4`));
202
- replacedTargets.add(target);
212
+ hasChanges = true;
203
213
  }
204
214
  else {
205
215
  // there are different args or the script has extra args, replace with the command leaving the args
206
216
  packageJson.scripts[scriptName] = packageJson.scripts[scriptName].replace(match, match.replace(commandRegex, configuration
207
217
  ? `$1nx ${target} --configuration=${configuration}$3`
208
218
  : `$1nx ${target}$3`));
209
- replacedTargets.add(target);
219
+ hasChanges = true;
210
220
  }
211
221
  }
212
222
  }
213
223
  }
214
224
  }
215
- (0, devkit_exports_1.writeJson)(tree, packageJsonPath, packageJson);
225
+ if (hasChanges) {
226
+ (0, devkit_exports_1.writeJson)(tree, packageJsonPath, packageJson);
227
+ }
216
228
  }
217
229
  function getInferredTargetCommands(project) {
218
230
  const targetCommands = [];
@@ -2,5 +2,6 @@ export interface AsyncPushCallbacks<T> {
2
2
  next: (value: T) => void;
3
3
  done: () => void;
4
4
  error: (err: unknown) => void;
5
+ registerCleanup?: (cb: () => void | Promise<void>) => void;
5
6
  }
6
7
  export declare function createAsyncIterable<T = unknown>(listener: (ls: AsyncPushCallbacks<T>) => void): AsyncIterable<T>;
@@ -4,6 +4,7 @@ exports.createAsyncIterable = createAsyncIterable;
4
4
  function createAsyncIterable(listener) {
5
5
  let done = false;
6
6
  let error = null;
7
+ let cleanup;
7
8
  const pushQueue = [];
8
9
  const pullQueue = [];
9
10
  return {
@@ -33,6 +34,9 @@ function createAsyncIterable(listener) {
33
34
  }
34
35
  done = true;
35
36
  },
37
+ registerCleanup: (cb) => {
38
+ cleanup = cb;
39
+ },
36
40
  });
37
41
  return {
38
42
  next() {
@@ -51,6 +55,12 @@ function createAsyncIterable(listener) {
51
55
  }
52
56
  });
53
57
  },
58
+ async return() {
59
+ if (cleanup) {
60
+ await cleanup();
61
+ }
62
+ return { value: undefined, done: true };
63
+ },
54
64
  };
55
65
  },
56
66
  };
@@ -191,6 +191,7 @@ const binaryExtensions = new Set([
191
191
  '.resources',
192
192
  '.rgb',
193
193
  '.rip',
194
+ '.riv',
194
195
  '.rlc',
195
196
  '.rmf',
196
197
  '.rmvb',
@@ -1,2 +1,3 @@
1
1
  import { CreateNodesContext, CreateNodesContextV2 } from 'nx/src/devkit-exports';
2
2
  export declare function calculateHashForCreateNodes(projectRoot: string, options: object, context: CreateNodesContext | CreateNodesContextV2, additionalGlobs?: string[]): Promise<string>;
3
+ export declare function calculateHashesForCreateNodes(projectRoots: string[], options: object, context: CreateNodesContext | CreateNodesContextV2, additionalGlobs?: string[][]): Promise<string[]>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateHashForCreateNodes = calculateHashForCreateNodes;
4
+ exports.calculateHashesForCreateNodes = calculateHashesForCreateNodes;
4
5
  const path_1 = require("path");
5
6
  const devkit_exports_1 = require("nx/src/devkit-exports");
6
7
  const devkit_internals_1 = require("nx/src/devkit-internals");
@@ -13,3 +14,15 @@ async function calculateHashForCreateNodes(projectRoot, options, context, additi
13
14
  (0, devkit_internals_1.hashObject)(options),
14
15
  ]);
15
16
  }
17
+ async function calculateHashesForCreateNodes(projectRoots, options, context, additionalGlobs = []) {
18
+ if (additionalGlobs.length &&
19
+ additionalGlobs.length !== projectRoots.length) {
20
+ throw new Error('If additionalGlobs is provided, it must be the same length as projectRoots');
21
+ }
22
+ return (0, devkit_internals_1.hashMultiGlobWithWorkspaceContext)(context.workspaceRoot, projectRoots.map((projectRoot, idx) => [
23
+ (0, path_1.join)(projectRoot, '**/*'),
24
+ ...(additionalGlobs.length ? additionalGlobs[idx] : []),
25
+ ])).then((hashes) => {
26
+ return hashes.map((hash) => (0, devkit_exports_1.hashArray)([hash, (0, devkit_internals_1.hashObject)(options)]));
27
+ });
28
+ }