nx 19.5.0-beta.1 → 19.5.0-beta.3
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -1
- package/package.json +12 -12
- package/schemas/project-schema.json +26 -0
- package/src/config/task-graph.d.ts +4 -0
- package/src/config/workspace-json-project-json.d.ts +5 -0
- package/src/native/index.d.ts +1 -0
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/native/transform-objects.js +1 -0
- package/src/project-graph/utils/project-configuration-utils.js +22 -2
- package/src/tasks-runner/create-task-graph.js +1 -0
- package/src/tasks-runner/tasks-schedule.d.ts +1 -0
- package/src/tasks-runner/tasks-schedule.js +28 -4
- package/src/tasks-runner/utils.js +2 -1
- package/src/utils/find-matching-projects.d.ts +0 -4
- package/src/utils/find-matching-projects.js +4 -7
- package/src/utils/globs.d.ts +2 -0
- package/src/utils/globs.js +11 -0
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://
|
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.
|
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.
|
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.
|
90
|
-
"@nx/nx-darwin-arm64": "19.5.0-beta.
|
91
|
-
"@nx/nx-linux-x64-gnu": "19.5.0-beta.
|
92
|
-
"@nx/nx-linux-x64-musl": "19.5.0-beta.
|
93
|
-
"@nx/nx-win32-x64-msvc": "19.5.0-beta.
|
94
|
-
"@nx/nx-linux-arm64-gnu": "19.5.0-beta.
|
95
|
-
"@nx/nx-linux-arm64-musl": "19.5.0-beta.
|
96
|
-
"@nx/nx-linux-arm-gnueabihf": "19.5.0-beta.
|
97
|
-
"@nx/nx-win32-arm64-msvc": "19.5.0-beta.
|
98
|
-
"@nx/nx-freebsd-x64": "19.5.0-beta.
|
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
|
}
|
package/src/native/index.d.ts
CHANGED
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
|
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(
|
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
|
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
|
-
|
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 (!
|
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 =
|
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 (!
|
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 (!
|
138
|
+
if (!(0, globs_1.isGlobPattern)(pattern.value)) {
|
142
139
|
continue;
|
143
140
|
}
|
144
141
|
if ((0, exports.getMatchingStringsWithCache)(pattern.value, tags).length) {
|
package/src/utils/globs.d.ts
CHANGED
package/src/utils/globs.js
CHANGED
@@ -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
|
+
}
|