nx 19.2.2 → 19.3.0-beta.0
Sign up to get free protection for your applications and to get access to all the features.
- package/bin/post-install.js +3 -1
- package/migrations.json +0 -6
- package/package.json +12 -12
- package/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +13 -38
- package/src/command-line/init/implementation/utils.js +2 -15
- package/src/command-line/release/version.d.ts +1 -1
- package/src/command-line/yargs-utils/shared-options.d.ts +1 -1
- package/src/core/graph/main.js +1 -1
- package/src/daemon/client/client.js +2 -0
- package/src/executors/run-commands/run-commands.impl.d.ts +1 -1
- package/src/executors/run-commands/run-commands.impl.js +11 -17
- package/src/hasher/file-hasher.js +1 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +1 -3
- package/src/plugins/package-json-workspaces/create-nodes.js +1 -10
- package/src/project-graph/error-types.js +0 -10
- package/src/project-graph/plugins/internal-api.js +1 -1
- package/src/project-graph/utils/normalize-project-nodes.js +6 -24
- package/src/project-graph/utils/project-configuration-utils.js +1 -9
- package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
- package/src/tasks-runner/create-task-graph.js +33 -32
- package/src/utils/ab-testing.d.ts +1 -1
- package/src/utils/find-matching-projects.js +1 -13
@@ -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
|
}
|
@@ -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
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
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.
|
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__,
|
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
|
-
|
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
|
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
|
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([
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
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("
|
12
|
+
allWorkspaceFiles: import("../file-utils").FileData[];
|
13
13
|
fileMap: {
|
14
14
|
projectFileMap: ProjectFiles;
|
15
|
-
nonProjectFiles: import("
|
15
|
+
nonProjectFiles: import("../../native").FileData[];
|
16
16
|
};
|
17
|
-
rustReferences: import("
|
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
|
-
|
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
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
}
|
108
|
-
|
109
|
-
|
110
|
-
|
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 =
|
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 =
|
143
|
+
const isExclude = pattern.startsWith('!');
|
156
144
|
// Support for things like: `!{type}:value`
|
157
145
|
if (isExclude) {
|
158
146
|
pattern = pattern.substring(1);
|