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 +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
|
+
}
|