nx 19.5.0-beta.1 → 19.5.0-beta.3

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
@@ -59,7 +59,7 @@ npx nx@latest init
59
59
  - [Nx.Dev: Documentation, Guides, Tutorials](https://nx.dev)
60
60
  - [Intro to Nx](https://nx.dev/getting-started/intro)
61
61
  - [Official Nx YouTube Channel](https://www.youtube.com/@NxDevtools)
62
- - [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
62
+ - [Blog Posts About Nx](https://nx.dev/blog)
63
63
 
64
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"
65
65
  width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "19.5.0-beta.1",
3
+ "version": "19.5.0-beta.3",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -71,7 +71,7 @@
71
71
  "yargs-parser": "21.1.1",
72
72
  "node-machine-id": "1.1.12",
73
73
  "ora": "5.3.0",
74
- "@nrwl/tao": "19.5.0-beta.1"
74
+ "@nrwl/tao": "19.5.0-beta.3"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "@swc-node/register": "^1.8.0",
@@ -86,16 +86,16 @@
86
86
  }
87
87
  },
88
88
  "optionalDependencies": {
89
- "@nx/nx-darwin-x64": "19.5.0-beta.1",
90
- "@nx/nx-darwin-arm64": "19.5.0-beta.1",
91
- "@nx/nx-linux-x64-gnu": "19.5.0-beta.1",
92
- "@nx/nx-linux-x64-musl": "19.5.0-beta.1",
93
- "@nx/nx-win32-x64-msvc": "19.5.0-beta.1",
94
- "@nx/nx-linux-arm64-gnu": "19.5.0-beta.1",
95
- "@nx/nx-linux-arm64-musl": "19.5.0-beta.1",
96
- "@nx/nx-linux-arm-gnueabihf": "19.5.0-beta.1",
97
- "@nx/nx-win32-arm64-msvc": "19.5.0-beta.1",
98
- "@nx/nx-freebsd-x64": "19.5.0-beta.1"
89
+ "@nx/nx-darwin-x64": "19.5.0-beta.3",
90
+ "@nx/nx-darwin-arm64": "19.5.0-beta.3",
91
+ "@nx/nx-linux-x64-gnu": "19.5.0-beta.3",
92
+ "@nx/nx-linux-x64-musl": "19.5.0-beta.3",
93
+ "@nx/nx-win32-x64-msvc": "19.5.0-beta.3",
94
+ "@nx/nx-linux-arm64-gnu": "19.5.0-beta.3",
95
+ "@nx/nx-linux-arm64-musl": "19.5.0-beta.3",
96
+ "@nx/nx-linux-arm-gnueabihf": "19.5.0-beta.3",
97
+ "@nx/nx-win32-arm64-msvc": "19.5.0-beta.3",
98
+ "@nx/nx-freebsd-x64": "19.5.0-beta.3"
99
99
  },
100
100
  "nx-migrations": {
101
101
  "migrations": "./migrations.json",
@@ -4,6 +4,27 @@
4
4
  "title": "JSON schema for Nx projects",
5
5
  "type": "object",
6
6
  "properties": {
7
+ "name": {
8
+ "type": "string",
9
+ "description": "Project's name. Optional if specified in workspace.json"
10
+ },
11
+ "root": {
12
+ "type": "string",
13
+ "description": "Project's location relative to the root of the workspace"
14
+ },
15
+ "sourceRoot": {
16
+ "type": "string",
17
+ "description": "The location of project's sources relative to the root of the workspace"
18
+ },
19
+ "projectType": {
20
+ "type": "string",
21
+ "description": "Type of project supported",
22
+ "enum": ["library", "application"]
23
+ },
24
+ "generators": {
25
+ "type": "object",
26
+ "description": "List of default values used by generators"
27
+ },
7
28
  "namedInputs": {
8
29
  "type": "object",
9
30
  "description": "Named inputs used by inputs defined in targets",
@@ -112,6 +133,11 @@
112
133
  "cache": {
113
134
  "type": "boolean",
114
135
  "description": "Specifies if the given target should be cacheable"
136
+ },
137
+ "parallelism": {
138
+ "type": "boolean",
139
+ "default": true,
140
+ "description": "Whether this target can be run in parallel with other tasks"
115
141
  }
116
142
  }
117
143
  }
@@ -80,6 +80,10 @@ export interface Task {
80
80
  * Determines if a given task should be cacheable.
81
81
  */
82
82
  cache?: boolean;
83
+ /**
84
+ * Determines if a given task should be parallelizable.
85
+ */
86
+ parallelism: boolean;
83
87
  }
84
88
  /**
85
89
  * Graph of Tasks to be executed
@@ -212,4 +212,9 @@ export interface TargetConfiguration<T = any> {
212
212
  * Metadata about the target
213
213
  */
214
214
  metadata?: TargetMetadata;
215
+ /**
216
+ * Whether this target can be run in parallel with other tasks
217
+ * Default is true
218
+ */
219
+ parallelism?: boolean;
215
220
  }
@@ -185,6 +185,7 @@ export interface Target {
185
185
  outputs?: Array<string>
186
186
  options?: string
187
187
  configurations?: string
188
+ parallelism?: boolean
188
189
  }
189
190
 
190
191
  export interface Task {
Binary file
@@ -14,6 +14,7 @@ function transformProjectGraphForRust(graph) {
14
14
  outputs: targetConfig.outputs,
15
15
  options: JSON.stringify(targetConfig.options),
16
16
  configurations: JSON.stringify(targetConfig.configurations),
17
+ parallelism: targetConfig.parallelism,
17
18
  };
18
19
  }
19
20
  nodes[projectName] = {
@@ -18,6 +18,7 @@ const minimatch_1 = require("minimatch");
18
18
  const path_1 = require("path");
19
19
  const perf_hooks_1 = require("perf_hooks");
20
20
  const error_types_1 = require("../error-types");
21
+ const globs_1 = require("../../utils/globs");
21
22
  function mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInformation,
22
23
  // This function is used when reading project configuration
23
24
  // in generators, where we don't want to do this.
@@ -709,10 +710,23 @@ function readTargetDefaultsForTarget(targetName, targetDefaults, executor) {
709
710
  const key = [executor, targetName].find((x) => targetDefaults?.[x]);
710
711
  return key ? targetDefaults?.[key] : null;
711
712
  }
712
- else {
713
+ else if (targetDefaults?.[targetName]) {
713
714
  // If the executor is not defined, the only key we have is the target name.
714
715
  return targetDefaults?.[targetName];
715
716
  }
717
+ let matchingTargetDefaultKey = null;
718
+ for (const key in targetDefaults ?? {}) {
719
+ if ((0, globs_1.isGlobPattern)(key) && (0, minimatch_1.minimatch)(targetName, key)) {
720
+ if (!matchingTargetDefaultKey ||
721
+ matchingTargetDefaultKey.length < key.length) {
722
+ matchingTargetDefaultKey = key;
723
+ }
724
+ }
725
+ }
726
+ if (matchingTargetDefaultKey) {
727
+ return targetDefaults[matchingTargetDefaultKey];
728
+ }
729
+ return {};
716
730
  }
717
731
  function createRootMap(projectRootMap) {
718
732
  const map = {};
@@ -748,11 +762,17 @@ function resolveCommandSyntacticSugar(target, key) {
748
762
  * @returns The normalized target configuration
749
763
  */
750
764
  function normalizeTarget(target, project) {
765
+ target = {
766
+ ...target,
767
+ configurations: {
768
+ ...target.configurations,
769
+ },
770
+ };
751
771
  target = resolveCommandSyntacticSugar(target, project.root);
752
772
  target.options = resolveNxTokensInOptions(target.options, project, `${project.root}:${target}`);
753
- target.configurations ??= {};
754
773
  for (const configuration in target.configurations) {
755
774
  target.configurations[configuration] = resolveNxTokensInOptions(target.configurations[configuration], project, `${project.root}:${target}:${configuration}`);
756
775
  }
776
+ target.parallelism ??= true;
757
777
  return target;
758
778
  }
@@ -156,6 +156,7 @@ class ProcessTasks {
156
156
  overrides: interpolatedOverrides,
157
157
  outputs: (0, utils_1.getOutputs)(this.projectGraph.nodes, qualifiedTarget, interpolatedOverrides),
158
158
  cache: project.data.targets[target].cache,
159
+ parallelism: project.data.targets[target].parallelism ?? true,
159
160
  };
160
161
  }
161
162
  resolveConfiguration(project, target, configuration) {
@@ -14,6 +14,7 @@ export declare class TasksSchedule {
14
14
  private reverseProjectGraph;
15
15
  private scheduledBatches;
16
16
  private scheduledTasks;
17
+ private runningTasks;
17
18
  private completedTasks;
18
19
  private scheduleRequestsExecutionChain;
19
20
  constructor(projectGraph: ProjectGraph, taskGraph: TaskGraph, options: DefaultTasksRunnerOptions);
@@ -14,6 +14,7 @@ class TasksSchedule {
14
14
  this.reverseProjectGraph = (0, operators_1.reverse)(this.projectGraph);
15
15
  this.scheduledBatches = [];
16
16
  this.scheduledTasks = [];
17
+ this.runningTasks = new Set();
17
18
  this.completedTasks = new Set();
18
19
  this.scheduleRequestsExecutionChain = Promise.resolve();
19
20
  }
@@ -31,6 +32,7 @@ class TasksSchedule {
31
32
  complete(taskIds) {
32
33
  for (const taskId of taskIds) {
33
34
  this.completedTasks.add(taskId);
35
+ this.runningTasks.delete(taskId);
34
36
  }
35
37
  this.notScheduledTaskGraph = (0, utils_1.removeTasksFromTaskGraph)(this.notScheduledTaskGraph, taskIds);
36
38
  }
@@ -84,6 +86,7 @@ class TasksSchedule {
84
86
  (0, project_graph_utils_1.findAllProjectNodeDependencies)(project1, this.reverseProjectGraph)
85
87
  .length);
86
88
  });
89
+ this.runningTasks.add(taskId);
87
90
  }
88
91
  async scheduleBatches() {
89
92
  const batchMap = {};
@@ -102,7 +105,7 @@ class TasksSchedule {
102
105
  this.scheduledBatches.push({ executorName, taskGraph });
103
106
  }
104
107
  async processTaskForBatches(batches, task, rootExecutorName, isRoot) {
105
- if (!this.canBatchTaskBeScheduled(task.id, batches[rootExecutorName])) {
108
+ if (!this.canBatchTaskBeScheduled(task, batches[rootExecutorName])) {
106
109
  return;
107
110
  }
108
111
  const { batchImplementationFactory } = (0, utils_1.getExecutorForTask)(task, this.projectGraph);
@@ -131,12 +134,33 @@ class TasksSchedule {
131
134
  await this.processTaskForBatches(batches, depTask, rootExecutorName, false);
132
135
  }
133
136
  }
134
- canBatchTaskBeScheduled(taskId, batchTaskGraph) {
137
+ canBatchTaskBeScheduled(task, batchTaskGraph) {
138
+ // task self needs to have parallelism true
135
139
  // all deps have either completed or belong to the same batch
136
- return this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id) || !!batchTaskGraph?.tasks[id]);
140
+ return (task.parallelism === true &&
141
+ this.taskGraph.dependencies[task.id].every((id) => this.completedTasks.has(id) || !!batchTaskGraph?.tasks[id]));
137
142
  }
138
143
  canBeScheduled(taskId) {
139
- return this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id));
144
+ const hasDependenciesCompleted = this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id));
145
+ // if dependencies have not completed, cannot schedule
146
+ if (!hasDependenciesCompleted) {
147
+ return false;
148
+ }
149
+ // if there are no running tasks, can schedule anything
150
+ if (this.runningTasks.size === 0) {
151
+ return true;
152
+ }
153
+ const runningTasksNotSupportParallelism = Array.from(this.runningTasks).some((taskId) => {
154
+ return this.taskGraph.tasks[taskId].parallelism === false;
155
+ });
156
+ if (runningTasksNotSupportParallelism) {
157
+ // if any running tasks do not support parallelism, no other tasks can be scheduled
158
+ return false;
159
+ }
160
+ else {
161
+ // if all running tasks support parallelism, can only schedule task with parallelism
162
+ return this.taskGraph.tasks[taskId].parallelism === true;
163
+ }
140
164
  }
141
165
  }
142
166
  exports.TasksSchedule = TasksSchedule;
@@ -36,6 +36,7 @@ const executor_utils_1 = require("../command-line/run/executor-utils");
36
36
  const project_graph_1 = require("../project-graph/project-graph");
37
37
  const find_matching_projects_1 = require("../utils/find-matching-projects");
38
38
  const minimatch_1 = require("minimatch");
39
+ const globs_1 = require("../utils/globs");
39
40
  function getDependencyConfigs({ project, target }, extraTargetDependencies, projectGraph, allTargetNames) {
40
41
  const dependencyConfigs = (projectGraph.nodes[project].data?.targets[target]?.dependsOn ??
41
42
  // This is passed into `run-command` from programmatic invocations
@@ -77,7 +78,7 @@ function expandDependencyConfigSyntaxSugar(dependencyConfigString, graph) {
77
78
  // Weakmap let's the cache get cleared by garbage collector if allTargetNames is no longer used
78
79
  const patternResultCache = new WeakMap();
79
80
  function expandWildcardTargetConfiguration(dependencyConfig, allTargetNames) {
80
- if (!find_matching_projects_1.GLOB_CHARACTERS.some((char) => dependencyConfig.target.includes(char))) {
81
+ if (!(0, globs_1.isGlobPattern)(dependencyConfig.target)) {
81
82
  return [dependencyConfig];
82
83
  }
83
84
  let cache = patternResultCache.get(allTargetNames);
@@ -1,8 +1,4 @@
1
1
  import type { ProjectGraphProjectNode } from '../config/project-graph';
2
- /**
3
- * The presence of these characters in a string indicates that it might be a glob pattern.
4
- */
5
- export declare const GLOB_CHARACTERS: string[];
6
2
  /**
7
3
  * Find matching project names given a list of potential project names or globs.
8
4
  *
@@ -1,18 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMatchingStringsWithCache = exports.GLOB_CHARACTERS = void 0;
3
+ exports.getMatchingStringsWithCache = void 0;
4
4
  exports.findMatchingProjects = findMatchingProjects;
5
5
  const minimatch_1 = require("minimatch");
6
+ const globs_1 = require("./globs");
6
7
  const validPatternTypes = [
7
8
  'name', // Pattern is based on the project's name
8
9
  'tag', // Pattern is based on the project's tags
9
10
  'directory', // Pattern is based on the project's root directory
10
11
  'unlabeled', // Pattern was passed without specifying a type
11
12
  ];
12
- /**
13
- * The presence of these characters in a string indicates that it might be a glob pattern.
14
- */
15
- exports.GLOB_CHARACTERS = ['*', '|', '{', '}', '(', ')'];
16
13
  /**
17
14
  * Find matching project names given a list of potential project names or globs.
18
15
  *
@@ -113,7 +110,7 @@ function addMatchingProjectsByName(projectNames, projects, pattern, matchedProje
113
110
  }
114
111
  return;
115
112
  }
116
- if (!exports.GLOB_CHARACTERS.some((c) => pattern.value.includes(c))) {
113
+ if (!(0, globs_1.isGlobPattern)(pattern.value)) {
117
114
  return;
118
115
  }
119
116
  const matchedProjectNames = (0, exports.getMatchingStringsWithCache)(pattern.value, projectNames);
@@ -138,7 +135,7 @@ function addMatchingProjectsByTag(projectNames, projects, pattern, matchedProjec
138
135
  }
139
136
  continue;
140
137
  }
141
- if (!exports.GLOB_CHARACTERS.some((c) => pattern.value.includes(c))) {
138
+ if (!(0, globs_1.isGlobPattern)(pattern.value)) {
142
139
  continue;
143
140
  }
144
141
  if ((0, exports.getMatchingStringsWithCache)(pattern.value, tags).length) {
@@ -1 +1,3 @@
1
1
  export declare function combineGlobPatterns(...patterns: (string | string[])[]): string;
2
+ export declare const GLOB_CHARACTERS: Set<string>;
3
+ export declare function isGlobPattern(pattern: string): boolean;
@@ -1,7 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GLOB_CHARACTERS = void 0;
3
4
  exports.combineGlobPatterns = combineGlobPatterns;
5
+ exports.isGlobPattern = isGlobPattern;
4
6
  function combineGlobPatterns(...patterns) {
5
7
  const p = patterns.flat();
6
8
  return p.length > 1 ? '{' + p.join(',') + '}' : p.length === 1 ? p[0] : '';
7
9
  }
10
+ exports.GLOB_CHARACTERS = new Set(['*', '|', '{', '}', '(', ')', '[']);
11
+ function isGlobPattern(pattern) {
12
+ for (const c of pattern) {
13
+ if (exports.GLOB_CHARACTERS.has(c)) {
14
+ return true;
15
+ }
16
+ }
17
+ return false;
18
+ }