nx 19.2.2 → 19.3.0-canary.20240606-bccb2c5

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,6 +19,7 @@ const nx_json_1 = require("../../config/nx-json");
19
19
  const daemon_socket_messenger_1 = require("./daemon-socket-messenger");
20
20
  const cache_1 = require("../cache");
21
21
  const error_types_1 = require("../../project-graph/error-types");
22
+ const dotenv_1 = require("../../utils/dotenv");
22
23
  const get_nx_workspace_files_1 = require("../message-types/get-nx-workspace-files");
23
24
  const get_context_file_data_1 = require("../message-types/get-context-file-data");
24
25
  const get_files_in_directory_1 = require("../message-types/get-files-in-directory");
@@ -40,6 +41,7 @@ class DaemonClient {
40
41
  this._daemonReady = null;
41
42
  this._out = null;
42
43
  this._err = null;
44
+ (0, dotenv_1.loadRootEnvFiles)(workspace_root_1.workspaceRoot);
43
45
  try {
44
46
  this.nxJson = (0, configuration_1.readNxJson)();
45
47
  }
@@ -42,7 +42,7 @@ export interface NormalizedRunCommandsOptions extends RunCommandsOptions {
42
42
  [k: string]: any;
43
43
  };
44
44
  unparsedCommandArgs?: {
45
- [k: string]: string | string[];
45
+ [k: string]: string;
46
46
  };
47
47
  args?: string;
48
48
  }
@@ -29,9 +29,7 @@ const propKeys = [
29
29
  'command',
30
30
  'commands',
31
31
  'color',
32
- 'no-color',
33
32
  'parallel',
34
- 'no-parallel',
35
33
  'readyWhen',
36
34
  'cwd',
37
35
  'args',
@@ -133,7 +131,6 @@ function normalizeOptions(options) {
133
131
  'parse-numbers': false,
134
132
  'parse-positional-numbers': false,
135
133
  'dot-notation': false,
136
- 'camel-case-expansion': false,
137
134
  },
138
135
  });
139
136
  options.unknownOptions = Object.keys(options)
@@ -297,21 +294,20 @@ function interpolateArgsIntoCommand(command, opts, forwardAllArgs) {
297
294
  else if (forwardAllArgs) {
298
295
  let args = '';
299
296
  if (Object.keys(opts.unknownOptions ?? {}).length > 0) {
300
- const unknownOptionsArgs = Object.keys(opts.unknownOptions)
301
- .filter((k) => typeof opts.unknownOptions[k] !== 'object' &&
302
- opts.parsedArgs[k] === opts.unknownOptions[k])
303
- .map((k) => `--${k}=${opts.unknownOptions[k]}`)
304
- .map(wrapArgIntoQuotesIfNeeded)
305
- .join(' ');
306
- if (unknownOptionsArgs) {
307
- args += ` ${unknownOptionsArgs}`;
308
- }
297
+ args +=
298
+ ' ' +
299
+ Object.keys(opts.unknownOptions)
300
+ .filter((k) => typeof opts.unknownOptions[k] !== 'object' &&
301
+ opts.parsedArgs[k] === opts.unknownOptions[k])
302
+ .map((k) => `--${k}=${opts.unknownOptions[k]}`)
303
+ .map(wrapArgIntoQuotesIfNeeded)
304
+ .join(' ');
309
305
  }
310
306
  if (opts.args) {
311
307
  args += ` ${opts.args}`;
312
308
  }
313
309
  if (opts.__unparsed__?.length > 0) {
314
- const filterdParsedOptions = filterPropKeysFromUnParsedOptions(opts.__unparsed__, opts.parsedArgs);
310
+ const filterdParsedOptions = filterPropKeysFromUnParsedOptions(opts.__unparsed__, opts.unparsedCommandArgs);
315
311
  if (filterdParsedOptions.length > 0) {
316
312
  args += ` ${filterdParsedOptions
317
313
  .map(wrapArgIntoQuotesIfNeeded)
@@ -339,14 +335,13 @@ function parseArgs(unparsedCommandArgs, unknownOptions, args) {
339
335
  * @param unparsedCommandArgs e.g. { prop1: 'value1', prop2: 'value2', args: 'test'}
340
336
  * @returns filtered options that are not part of the propKeys array e.g. ['--prop1', 'value1', '--prop2=value2']
341
337
  */
342
- function filterPropKeysFromUnParsedOptions(__unparsed__, parseArgs = {}) {
338
+ function filterPropKeysFromUnParsedOptions(__unparsed__, unparsedCommandArgs = {}) {
343
339
  const parsedOptions = [];
344
340
  for (let index = 0; index < __unparsed__.length; index++) {
345
341
  const element = __unparsed__[index];
346
342
  if (element.startsWith('--')) {
347
343
  const key = element.replace('--', '');
348
344
  if (element.includes('=')) {
349
- // key can be in the format of --key=value or --key.subkey=value (e.g. env.foo=bar)
350
345
  if (!propKeys.includes(key.split('=')[0].split('.')[0])) {
351
346
  // check if the key is part of the propKeys array
352
347
  parsedOptions.push(element);
@@ -356,8 +351,7 @@ function filterPropKeysFromUnParsedOptions(__unparsed__, parseArgs = {}) {
356
351
  // check if the next element is a value for the key
357
352
  if (propKeys.includes(key)) {
358
353
  if (index + 1 < __unparsed__.length &&
359
- parseArgs[key] &&
360
- __unparsed__[index + 1].toString() === parseArgs[key].toString()) {
354
+ __unparsed__[index + 1] === unparsedCommandArgs[key]) {
361
355
  index++; // skip the next element
362
356
  }
363
357
  }
@@ -10,7 +10,7 @@ exports.hashArray = hashArray;
10
10
  function hashObject(obj) {
11
11
  const { hashArray } = require('../native');
12
12
  const parts = [];
13
- for (const key of Object.keys(obj ?? {}).sort()) {
13
+ for (const key of Object.keys(obj).sort()) {
14
14
  parts.push(key);
15
15
  parts.push(JSON.stringify(obj[key]));
16
16
  }
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TargetProjectLocator = exports.isBuiltinModuleImport = void 0;
4
4
  const node_module_1 = require("node:module");
5
5
  const node_path_1 = require("node:path");
6
- const semver_1 = require("semver");
7
6
  const find_project_for_path_1 = require("../../../../project-graph/utils/find-project-for-path");
8
7
  const fileutils_1 = require("../../../../utils/fileutils");
9
8
  const workspace_root_1 = require("../../../../utils/workspace-root");
@@ -139,8 +138,7 @@ class TargetProjectLocator {
139
138
  this.npmResolutionCache.set(npmImportForProject, externalNodeName);
140
139
  return externalNodeName;
141
140
  }
142
- const version = (0, semver_1.clean)(externalPackageJson.version);
143
- const npmProjectKey = `npm:${externalPackageJson.name}@${version}`;
141
+ const npmProjectKey = `npm:${externalPackageJson.name}@${externalPackageJson.version}`;
144
142
  const matchingExternalNode = this.npmProjects[npmProjectKey];
145
143
  if (!matchingExternalNode) {
146
144
  return null;
@@ -38,16 +38,7 @@ function buildPackageJsonWorkspacesMatcher(workspaceRoot, readJson) {
38
38
  positivePatterns.push('**/package.json');
39
39
  }
40
40
  return (p) => positivePatterns.some((positive) => (0, minimatch_1.minimatch)(p, positive)) &&
41
- /**
42
- * minimatch will return true if the given p is NOT excluded by the negative pattern.
43
- *
44
- * For example if the negative pattern is "!packages/vite", then the given p "packages/vite" will return false,
45
- * the given p "packages/something-else/package.json" will return true.
46
- *
47
- * Therefore, we need to ensure that every negative pattern returns true to validate that the given p is not
48
- * excluded by any of the negative patterns.
49
- */
50
- negativePatterns.every((negative) => (0, minimatch_1.minimatch)(p, negative));
41
+ !negativePatterns.some((negative) => (0, minimatch_1.minimatch)(p, negative));
51
42
  }
52
43
  exports.buildPackageJsonWorkspacesMatcher = buildPackageJsonWorkspacesMatcher;
53
44
  function createNodeFromPackageJson(pkgJsonPath, root) {
@@ -161,16 +161,6 @@ class AggregateCreateNodesError extends Error {
161
161
  this.errors = errors;
162
162
  this.partialResults = partialResults;
163
163
  this.name = this.constructor.name;
164
- if (
165
- // Errors should be an array
166
- !Array.isArray(errors) ||
167
- !errors.every(
168
- // Where every element is a tuple
169
- (errorTuple) => Array.isArray(errorTuple) &&
170
- // That has a length of 2
171
- errorTuple.length === 2)) {
172
- throw new Error('AggregateCreateNodesError must be constructed with an array of tuples where the first element is a filename or undefined and the second element is the underlying error.');
173
- }
174
164
  }
175
165
  }
176
166
  exports.AggregateCreateNodesError = AggregateCreateNodesError;
@@ -45,7 +45,7 @@ class LoadedNxPlugin {
45
45
  throw e;
46
46
  }
47
47
  // The underlying plugin errored out. We can't know any partial results.
48
- throw new error_types_1.AggregateCreateNodesError([[null, e]], []);
48
+ throw new error_types_1.AggregateCreateNodesError([null, e], []);
49
49
  }
50
50
  finally {
51
51
  performance.mark(`${plugin.name}:createNodes - end`);
@@ -76,29 +76,11 @@ function normalizeImplicitDependencies(source, implicitDependencies, projects) {
76
76
  if (!implicitDependencies?.length) {
77
77
  return implicitDependencies ?? [];
78
78
  }
79
- // Implicit dependencies handle negatives in a different
80
- // way from most other `projects` fields. This is because
81
- // they are used for multiple purposes.
82
- const positivePatterns = [];
83
- const negativePatterns = [];
84
- for (const dep of implicitDependencies) {
85
- if (dep.startsWith('!')) {
86
- negativePatterns.push(dep);
87
- }
88
- else {
89
- positivePatterns.push(dep);
90
- }
91
- }
92
- // Finds all projects that match a positive pattern and are not excluded by a negative pattern
93
- const deps = positivePatterns.length
94
- ? (0, find_matching_projects_1.findMatchingProjects)(positivePatterns.concat(negativePatterns), projects).filter((x) => x !== source)
95
- : [];
96
- // Expands negative patterns to equal project names
97
- const alwaysIgnoredDeps = (0, find_matching_projects_1.findMatchingProjects)(negativePatterns.map((x) => x.slice(1)), projects);
98
- // We return the matching deps, but keep the negative patterns in the list
99
- // so that they can be processed later by implicit-project-dependencies.ts
100
- // This is what allows using a negative implicit dep to remove a dependency
101
- // detected by createDependencies.
102
- return deps.concat(alwaysIgnoredDeps.map((x) => '!' + x));
79
+ const matches = (0, find_matching_projects_1.findMatchingProjects)(implicitDependencies, projects);
80
+ return (matches
81
+ .filter((x) => x !== source)
82
+ // implicit dependencies that start with ! should hang around, to be processed by
83
+ // implicit-project-dependencies.ts after explicit deps are added to graph.
84
+ .concat(implicitDependencies.filter((x) => x.startsWith('!'))));
103
85
  }
104
86
  exports.normalizeImplicitDependencies = normalizeImplicitDependencies;
@@ -245,15 +245,7 @@ plugins) {
245
245
  e
246
246
  : // This represents a single plugin erroring out with a hard error.
247
247
  new error_types_1.AggregateCreateNodesError([[null, e]], []);
248
- const innerErrors = error.errors;
249
- for (const [file, e] of innerErrors) {
250
- if (file) {
251
- errorBodyLines.push(` - ${file}: ${e.message}`);
252
- }
253
- else {
254
- errorBodyLines.push(` - ${e.message}`);
255
- }
256
- }
248
+ errorBodyLines.push(...error.errors.map(([file, e]) => ` - ${file}: ${e.message}`));
257
249
  error.message = errorBodyLines.join('\n');
258
250
  // This represents a single plugin erroring out with a hard error.
259
251
  errors.push(error);
@@ -9,12 +9,12 @@ import { LoadedNxPlugin } from '../plugins/internal-api';
9
9
  * @param nxJson
10
10
  */
11
11
  export declare function retrieveWorkspaceFiles(workspaceRoot: string, projectRootMap: Record<string, string>): Promise<{
12
- allWorkspaceFiles: import("nx/src/devkit-exports").FileData[];
12
+ allWorkspaceFiles: import("../file-utils").FileData[];
13
13
  fileMap: {
14
14
  projectFileMap: ProjectFiles;
15
- nonProjectFiles: import("nx/src/native").FileData[];
15
+ nonProjectFiles: import("../../native").FileData[];
16
16
  };
17
- rustReferences: import("nx/src/native").NxWorkspaceFilesExternals;
17
+ rustReferences: import("../../native").NxWorkspaceFilesExternals;
18
18
  }>;
19
19
  /**
20
20
  * Walk through the workspace and return `ProjectConfigurations`. Only use this if the projectFileMap is not needed.
@@ -64,26 +64,7 @@ class ProcessTasks {
64
64
  ? overrides
65
65
  : { __overrides_unparsed__: [] };
66
66
  if (dependencyConfig.projects) {
67
- /** LERNA SUPPORT START - Remove in v20 */
68
- // Lerna uses `dependencies` in `prepNxOptions`, so we need to maintain
69
- // support for it until lerna can be updated to use the syntax.
70
- //
71
- // This should have been removed in v17, but the updates to lerna had not
72
- // been made yet.
73
- //
74
- // TODO(@agentender): Remove this part in v20
75
- if (typeof dependencyConfig.projects === 'string') {
76
- if (dependencyConfig.projects === 'self') {
77
- this.processTasksForSingleProject(task, task.target.project, dependencyConfig, configuration, taskOverrides, overrides);
78
- continue;
79
- }
80
- else if (dependencyConfig.projects === 'dependencies') {
81
- this.processTasksForDependencies(projectUsedToDeriveDependencies, dependencyConfig, configuration, task, taskOverrides, overrides);
82
- continue;
83
- }
84
- }
85
- /** LERNA SUPPORT END - Remove in v17 */
86
- this.processTasksForMatchingProjects(dependencyConfig, configuration, task, taskOverrides, overrides);
67
+ this.processTasksForMatchingProjects(dependencyConfig, projectUsedToDeriveDependencies, configuration, task, taskOverrides, overrides);
87
68
  }
88
69
  else if (dependencyConfig.dependencies) {
89
70
  this.processTasksForDependencies(projectUsedToDeriveDependencies, dependencyConfig, configuration, task, taskOverrides, overrides);
@@ -93,21 +74,41 @@ class ProcessTasks {
93
74
  }
94
75
  }
95
76
  }
96
- processTasksForMatchingProjects(dependencyConfig, configuration, task, taskOverrides, overrides) {
77
+ processTasksForMatchingProjects(dependencyConfig, projectUsedToDeriveDependencies, configuration, task, taskOverrides, overrides) {
97
78
  const targetProjectSpecifiers = typeof dependencyConfig.projects === 'string'
98
79
  ? [dependencyConfig.projects]
99
80
  : dependencyConfig.projects;
100
- const matchingProjects = (0, find_matching_projects_1.findMatchingProjects)(targetProjectSpecifiers, this.projectGraph.nodes);
101
- if (matchingProjects.length === 0) {
102
- output_1.output.warn({
103
- title: `\`dependsOn\` is misconfigured for ${task.target.project}:${task.target.target}`,
104
- bodyLines: [
105
- `Project patterns "${targetProjectSpecifiers}" does not match any projects.`,
106
- ],
107
- });
108
- }
109
- for (const projectName of matchingProjects) {
110
- this.processTasksForSingleProject(task, projectName, dependencyConfig, configuration, taskOverrides, overrides);
81
+ for (const projectSpecifier of targetProjectSpecifiers) {
82
+ // Lerna uses `dependencies` in `prepNxOptions`, so we need to maintain
83
+ // support for it until lerna can be updated to use the syntax.
84
+ // TODO(@agentender): Remove this part in v17
85
+ if (projectSpecifier === 'dependencies' &&
86
+ !this.projectGraph.nodes[projectSpecifier]) {
87
+ this.processTasksForDependencies(projectUsedToDeriveDependencies, dependencyConfig, configuration, task, taskOverrides, overrides);
88
+ }
89
+ else {
90
+ // Since we need to maintain support for dependencies, it is more coherent
91
+ // that we also support self.
92
+ // TODO(@agentender): Remove this part in v17
93
+ const matchingProjects =
94
+ /** LERNA SUPPORT START - Remove in v17 */
95
+ projectSpecifier === 'self' &&
96
+ !this.projectGraph.nodes[projectSpecifier]
97
+ ? [task.target.project]
98
+ : /** LERNA SUPPORT END */
99
+ (0, find_matching_projects_1.findMatchingProjects)([projectSpecifier], this.projectGraph.nodes);
100
+ if (matchingProjects.length === 0) {
101
+ output_1.output.warn({
102
+ title: `\`dependsOn\` is misconfigured for ${task.target.project}:${task.target.target}`,
103
+ bodyLines: [
104
+ `Project pattern "${projectSpecifier}" does not match any projects.`,
105
+ ],
106
+ });
107
+ }
108
+ for (const projectName of matchingProjects) {
109
+ this.processTasksForSingleProject(task, projectName, dependencyConfig, configuration, taskOverrides, overrides);
110
+ }
111
+ }
111
112
  }
112
113
  }
113
114
  processTasksForSingleProject(task, projectName, dependencyConfig, configuration, taskOverrides, overrides) {
@@ -31,7 +31,7 @@ declare const messageOptions: {
31
31
  }];
32
32
  };
33
33
  export type MessageKey = keyof typeof messageOptions;
34
- export type MessageData = (typeof messageOptions)[MessageKey][number];
34
+ export type MessageData = typeof messageOptions[MessageKey][number];
35
35
  export declare class PromptMessages {
36
36
  private selectedMessages;
37
37
  getPrompt(key: MessageKey): MessageData;
@@ -22,15 +22,6 @@ function findMatchingProjects(patterns = [], projects) {
22
22
  }
23
23
  const projectNames = Object.keys(projects);
24
24
  const matchedProjects = new Set();
25
- // If the first pattern is an exclude pattern,
26
- // we add a wildcard pattern at the first to select
27
- // all projects, except the ones that match the exclude pattern.
28
- // e.g. ['!tag:someTag', 'project2'] will match all projects except
29
- // the ones with the tag 'someTag', and also match the project 'project2',
30
- // regardless of its tags.
31
- if (isExcludePattern(patterns[0])) {
32
- patterns.unshift('*');
33
- }
34
25
  for (const stringPattern of patterns) {
35
26
  if (!stringPattern.length) {
36
27
  continue;
@@ -148,11 +139,8 @@ function addMatchingProjectsByTag(projectNames, projects, pattern, matchedProjec
148
139
  }
149
140
  }
150
141
  }
151
- function isExcludePattern(pattern) {
152
- return pattern.startsWith('!');
153
- }
154
142
  function parseStringPattern(pattern, projects) {
155
- const isExclude = isExcludePattern(pattern);
143
+ const isExclude = pattern.startsWith('!');
156
144
  // Support for things like: `!{type}:value`
157
145
  if (isExclude) {
158
146
  pattern = pattern.substring(1);