nx 18.1.1 → 18.2.0-beta.0

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.
Files changed (47) hide show
  1. package/package.json +12 -12
  2. package/src/adapter/compat.d.ts +1 -1
  3. package/src/adapter/compat.js +1 -0
  4. package/src/command-line/add/add.js +1 -1
  5. package/src/command-line/affected/command-object.js +49 -22
  6. package/src/command-line/generate/generate.js +3 -3
  7. package/src/command-line/init/init-v2.js +43 -31
  8. package/src/command-line/run/command-object.js +9 -2
  9. package/src/command-line/run/run-one.js +1 -1
  10. package/src/command-line/run/run.js +15 -5
  11. package/src/command-line/run-many/command-object.js +4 -1
  12. package/src/command-line/show/command-object.d.ts +2 -0
  13. package/src/command-line/show/command-object.js +19 -2
  14. package/src/config/workspace-json-project-json.d.ts +4 -0
  15. package/src/core/graph/main.js +1 -1
  16. package/src/core/graph/polyfills.js +1 -1
  17. package/src/daemon/client/client.js +19 -7
  18. package/src/daemon/daemon-project-graph-error.d.ts +8 -0
  19. package/src/daemon/daemon-project-graph-error.js +13 -0
  20. package/src/daemon/server/handle-hash-tasks.js +11 -1
  21. package/src/daemon/server/project-graph-incremental-recomputation.d.ts +1 -0
  22. package/src/daemon/server/project-graph-incremental-recomputation.js +55 -6
  23. package/src/daemon/server/shutdown-utils.js +1 -3
  24. package/src/daemon/socket-utils.js +7 -1
  25. package/src/executors/run-commands/run-commands.impl.js +15 -9
  26. package/src/executors/run-script/run-script.impl.js +1 -1
  27. package/src/plugins/js/index.js +1 -1
  28. package/src/plugins/js/lock-file/lock-file.d.ts +2 -2
  29. package/src/plugins/js/lock-file/lock-file.js +2 -2
  30. package/src/plugins/js/versions.d.ts +1 -1
  31. package/src/plugins/js/versions.js +1 -1
  32. package/src/project-graph/build-project-graph.d.ts +18 -1
  33. package/src/project-graph/build-project-graph.js +71 -24
  34. package/src/project-graph/project-graph.d.ts +23 -2
  35. package/src/project-graph/project-graph.js +117 -14
  36. package/src/project-graph/utils/project-configuration-utils.d.ts +27 -4
  37. package/src/project-graph/utils/project-configuration-utils.js +176 -45
  38. package/src/project-graph/utils/retrieve-workspace-files.d.ts +6 -14
  39. package/src/project-graph/utils/retrieve-workspace-files.js +3 -16
  40. package/src/tasks-runner/forked-process-task-runner.d.ts +2 -1
  41. package/src/tasks-runner/forked-process-task-runner.js +19 -8
  42. package/src/tasks-runner/pseudo-terminal.d.ts +2 -1
  43. package/src/tasks-runner/pseudo-terminal.js +27 -1
  44. package/src/tasks-runner/task-orchestrator.js +4 -22
  45. package/src/utils/output.d.ts +1 -1
  46. package/src/utils/params.d.ts +2 -2
  47. package/src/utils/params.js +14 -0
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
+ var _ProjectGraphError_errors, _ProjectGraphError_partialProjectGraph, _ProjectGraphError_partialSourceMaps;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createProjectGraphAndSourceMapsAsync = exports.createProjectGraphAsync = exports.buildProjectGraphAndSourceMapsWithoutDaemon = exports.readProjectsConfigurationFromProjectGraph = exports.readCachedProjectConfiguration = exports.readCachedProjectGraph = void 0;
4
+ exports.createProjectGraphAndSourceMapsAsync = exports.createProjectGraphAsync = exports.ProjectGraphError = exports.buildProjectGraphAndSourceMapsWithoutDaemon = exports.readProjectsConfigurationFromProjectGraph = exports.readCachedProjectConfiguration = exports.readCachedProjectGraph = void 0;
5
+ const tslib_1 = require("tslib");
4
6
  const nx_deps_cache_1 = require("./nx-deps-cache");
5
7
  const build_project_graph_1 = require("./build-project-graph");
6
8
  const output_1 = require("../utils/output");
@@ -13,6 +15,7 @@ const perf_hooks_1 = require("perf_hooks");
13
15
  const retrieve_workspace_files_1 = require("./utils/retrieve-workspace-files");
14
16
  const nx_json_1 = require("../config/nx-json");
15
17
  const nx_plugin_1 = require("../utils/nx-plugin");
18
+ const project_configuration_utils_1 = require("./utils/project-configuration-utils");
16
19
  /**
17
20
  * Synchronously reads the latest cached copy of the workspace's ProjectGraph.
18
21
  * @throws {Error} if there is no cached ProjectGraph to read from
@@ -70,29 +73,127 @@ async function buildProjectGraphAndSourceMapsWithoutDaemon() {
70
73
  global.NX_GRAPH_CREATION = true;
71
74
  const nxJson = (0, nx_json_1.readNxJson)();
72
75
  perf_hooks_1.performance.mark('retrieve-project-configurations:start');
73
- const { projects, externalNodes, sourceMaps, projectRootMap } = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(workspace_root_1.workspaceRoot, nxJson);
76
+ let configurationResult;
77
+ let projectConfigurationsError;
78
+ try {
79
+ configurationResult = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(workspace_root_1.workspaceRoot, nxJson);
80
+ }
81
+ catch (e) {
82
+ if (e instanceof project_configuration_utils_1.ProjectConfigurationsError) {
83
+ projectConfigurationsError = e;
84
+ configurationResult = e.partialProjectConfigurationsResult;
85
+ }
86
+ else {
87
+ throw e;
88
+ }
89
+ }
90
+ const { projects, externalNodes, sourceMaps, projectRootMap } = configurationResult;
74
91
  perf_hooks_1.performance.mark('retrieve-project-configurations:end');
75
92
  perf_hooks_1.performance.mark('retrieve-workspace-files:start');
76
93
  const { allWorkspaceFiles, fileMap, rustReferences } = await (0, retrieve_workspace_files_1.retrieveWorkspaceFiles)(workspace_root_1.workspaceRoot, projectRootMap);
77
94
  perf_hooks_1.performance.mark('retrieve-workspace-files:end');
78
95
  const cacheEnabled = process.env.NX_CACHE_PROJECT_GRAPH !== 'false';
79
96
  perf_hooks_1.performance.mark('build-project-graph-using-project-file-map:start');
80
- const projectGraph = (await (0, build_project_graph_1.buildProjectGraphUsingProjectFileMap)(projects, externalNodes, fileMap, allWorkspaceFiles, rustReferences, cacheEnabled ? (0, nx_deps_cache_1.readFileMapCache)() : null, cacheEnabled)).projectGraph;
97
+ let createDependenciesError;
98
+ let projectGraphResult;
99
+ try {
100
+ projectGraphResult = await (0, build_project_graph_1.buildProjectGraphUsingProjectFileMap)(projects, externalNodes, fileMap, allWorkspaceFiles, rustReferences, cacheEnabled ? (0, nx_deps_cache_1.readFileMapCache)() : null);
101
+ }
102
+ catch (e) {
103
+ if (e instanceof build_project_graph_1.CreateDependenciesError) {
104
+ projectGraphResult = {
105
+ projectGraph: e.partialProjectGraph,
106
+ projectFileMapCache: null,
107
+ };
108
+ createDependenciesError = e;
109
+ }
110
+ else {
111
+ throw e;
112
+ }
113
+ }
114
+ const { projectGraph, projectFileMapCache } = projectGraphResult;
81
115
  perf_hooks_1.performance.mark('build-project-graph-using-project-file-map:end');
82
116
  (0, nx_plugin_1.unregisterPluginTSTranspiler)();
83
117
  delete global.NX_GRAPH_CREATION;
84
- return { projectGraph, sourceMaps };
118
+ const errors = [
119
+ ...(projectConfigurationsError?.errors ?? []),
120
+ ...(createDependenciesError?.errors ?? []),
121
+ ];
122
+ if (errors.length > 0) {
123
+ throw new ProjectGraphError(errors, projectGraph, sourceMaps);
124
+ }
125
+ else {
126
+ if (cacheEnabled) {
127
+ (0, nx_deps_cache_1.writeCache)(projectFileMapCache, projectGraph);
128
+ }
129
+ return { projectGraph, sourceMaps };
130
+ }
85
131
  }
86
132
  exports.buildProjectGraphAndSourceMapsWithoutDaemon = buildProjectGraphAndSourceMapsWithoutDaemon;
133
+ class ProjectGraphError extends Error {
134
+ constructor(errors, partialProjectGraph, partialSourceMaps) {
135
+ super(`Failed to process project graph.`);
136
+ _ProjectGraphError_errors.set(this, void 0);
137
+ _ProjectGraphError_partialProjectGraph.set(this, void 0);
138
+ _ProjectGraphError_partialSourceMaps.set(this, void 0);
139
+ this.name = this.constructor.name;
140
+ tslib_1.__classPrivateFieldSet(this, _ProjectGraphError_errors, errors, "f");
141
+ tslib_1.__classPrivateFieldSet(this, _ProjectGraphError_partialProjectGraph, partialProjectGraph, "f");
142
+ tslib_1.__classPrivateFieldSet(this, _ProjectGraphError_partialSourceMaps, partialSourceMaps, "f");
143
+ this.stack = `${this.message}\n ${errors
144
+ .map((error) => error.stack.split('\n').join('\n '))
145
+ .join('\n')}`;
146
+ }
147
+ /**
148
+ * The daemon cannot throw errors which contain methods as they are not serializable.
149
+ *
150
+ * This method creates a new {@link ProjectGraphError} from a {@link DaemonProjectGraphError} with the methods based on the same serialized data.
151
+ */
152
+ static fromDaemonProjectGraphError(e) {
153
+ return new ProjectGraphError(e.errors, e.projectGraph, e.sourceMaps);
154
+ }
155
+ /**
156
+ * This gets the partial project graph despite the errors which occured.
157
+ * This partial project graph may be missing nodes, properties of nodes, or dependencies.
158
+ * This is useful mostly for visualization/debugging. It should not be used for running tasks.
159
+ */
160
+ getPartialProjectGraph() {
161
+ return tslib_1.__classPrivateFieldGet(this, _ProjectGraphError_partialProjectGraph, "f");
162
+ }
163
+ getPartialSourcemaps() {
164
+ return tslib_1.__classPrivateFieldGet(this, _ProjectGraphError_partialSourceMaps, "f");
165
+ }
166
+ getErrors() {
167
+ return tslib_1.__classPrivateFieldGet(this, _ProjectGraphError_errors, "f");
168
+ }
169
+ }
170
+ exports.ProjectGraphError = ProjectGraphError;
171
+ _ProjectGraphError_errors = new WeakMap(), _ProjectGraphError_partialProjectGraph = new WeakMap(), _ProjectGraphError_partialSourceMaps = new WeakMap();
87
172
  function handleProjectGraphError(opts, e) {
88
173
  if (opts.exitOnError) {
89
- const lines = e.message.split('\n');
90
- output_1.output.error({
91
- title: lines[0],
92
- bodyLines: lines.slice(1),
93
- });
94
- if (process.env.NX_VERBOSE_LOGGING === 'true') {
95
- console.error(e);
174
+ const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true';
175
+ if (e instanceof ProjectGraphError) {
176
+ let title = e.message;
177
+ if (isVerbose) {
178
+ title += ' See errors below.';
179
+ }
180
+ const bodyLines = isVerbose
181
+ ? [e.stack]
182
+ : ['Pass --verbose to see the stacktraces.'];
183
+ output_1.output.error({
184
+ title,
185
+ bodyLines: bodyLines,
186
+ });
187
+ }
188
+ else {
189
+ const lines = e.message.split('\n');
190
+ output_1.output.error({
191
+ title: lines[0],
192
+ bodyLines: lines.slice(1),
193
+ });
194
+ if (isVerbose) {
195
+ console.error(e);
196
+ }
96
197
  }
97
198
  process.exit(1);
98
199
  }
@@ -151,9 +252,6 @@ async function createProjectGraphAndSourceMapsAsync(opts = {
151
252
  else {
152
253
  try {
153
254
  const projectGraphAndSourceMaps = await client_1.daemonClient.getProjectGraphAndSourceMaps();
154
- if (opts.resetDaemonClient) {
155
- client_1.daemonClient.reset();
156
- }
157
255
  perf_hooks_1.performance.mark('create-project-graph-async:end');
158
256
  perf_hooks_1.performance.measure('create-project-graph-async', 'create-project-graph-async:start', 'create-project-graph-async:end');
159
257
  return projectGraphAndSourceMaps;
@@ -186,6 +284,11 @@ async function createProjectGraphAndSourceMapsAsync(opts = {
186
284
  }
187
285
  handleProjectGraphError(opts, e);
188
286
  }
287
+ finally {
288
+ if (opts.resetDaemonClient) {
289
+ client_1.daemonClient.reset();
290
+ }
291
+ }
189
292
  }
190
293
  }
191
294
  exports.createProjectGraphAndSourceMapsAsync = createProjectGraphAndSourceMapsAsync;
@@ -13,20 +13,43 @@ export declare function mergeProjectConfigurationIntoRootMap(projectRootMap: Map
13
13
  export type ConfigurationResult = {
14
14
  projects: Record<string, ProjectConfiguration>;
15
15
  externalNodes: Record<string, ProjectGraphExternalNode>;
16
- rootMap: Record<string, string>;
16
+ projectRootMap: Record<string, string>;
17
17
  sourceMaps: ConfigurationSourceMaps;
18
18
  };
19
19
  /**
20
20
  * Transforms a list of project paths into a map of project configurations.
21
21
  *
22
+ * @param root The workspace root
22
23
  * @param nxJson The NxJson configuration
23
24
  * @param workspaceFiles A list of non-ignored workspace files
24
25
  * @param plugins The plugins that should be used to infer project configuration
25
- * @param root The workspace root
26
26
  */
27
- export declare function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson: NxJsonConfiguration, workspaceFiles: string[], // making this parameter allows devkit to pick up newly created projects
28
- plugins: LoadedNxPlugin[], root?: string): Promise<ConfigurationResult>;
27
+ export declare function createProjectConfigurations(root: string, nxJson: NxJsonConfiguration, workspaceFiles: string[], // making this parameter allows devkit to pick up newly created projects
28
+ plugins: LoadedNxPlugin[]): Promise<ConfigurationResult>;
29
29
  export declare function readProjectConfigurationsFromRootMap(projectRootMap: Map<string, ProjectConfiguration>): Record<string, ProjectConfiguration>;
30
+ export declare class ProjectConfigurationsError extends Error {
31
+ readonly errors: Array<MergeNodesError | CreateNodesError>;
32
+ readonly partialProjectConfigurationsResult: ConfigurationResult;
33
+ constructor(errors: Array<MergeNodesError | CreateNodesError>, partialProjectConfigurationsResult: ConfigurationResult);
34
+ }
35
+ export declare class CreateNodesError extends Error {
36
+ file: string;
37
+ pluginName: string;
38
+ constructor({ file, pluginName, error, }: {
39
+ file: string;
40
+ pluginName: string;
41
+ error: Error;
42
+ });
43
+ }
44
+ export declare class MergeNodesError extends Error {
45
+ file: string;
46
+ pluginName: string;
47
+ constructor({ file, pluginName, error, }: {
48
+ file: string;
49
+ pluginName: string;
50
+ error: Error;
51
+ });
52
+ }
30
53
  /**
31
54
  * Merges two targets.
32
55
  *
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readTargetDefaultsForTarget = exports.resolveNxTokensInOptions = exports.isCompatibleTarget = exports.mergeTargetConfigurations = exports.readProjectConfigurationsFromRootMap = exports.buildProjectsConfigurationsFromProjectPathsAndPlugins = exports.mergeProjectConfigurationIntoRootMap = void 0;
3
+ exports.readTargetDefaultsForTarget = exports.resolveNxTokensInOptions = exports.isCompatibleTarget = exports.mergeTargetConfigurations = exports.MergeNodesError = exports.CreateNodesError = exports.ProjectConfigurationsError = exports.readProjectConfigurationsFromRootMap = exports.createProjectConfigurations = exports.mergeProjectConfigurationIntoRootMap = void 0;
4
4
  const logger_1 = require("../../utils/logger");
5
5
  const fileutils_1 = require("../../utils/fileutils");
6
6
  const workspace_root_1 = require("../../utils/workspace-root");
7
7
  const target_defaults_plugin_1 = require("../../plugins/target-defaults/target-defaults-plugin");
8
8
  const minimatch_1 = require("minimatch");
9
9
  const path_1 = require("path");
10
+ const perf_hooks_1 = require("perf_hooks");
10
11
  function mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInformation,
11
12
  // This function is used when reading project configuration
12
13
  // in generators, where we don't want to do this.
@@ -32,17 +33,27 @@ skipCommandNormalization) {
32
33
  // a project.json in which case it was already updated above.
33
34
  const updatedProjectConfiguration = {
34
35
  ...matchingProject,
35
- ...project,
36
36
  };
37
- if (sourceMap) {
38
- for (const property in project) {
39
- sourceMap[`${property}`] = sourceInformation;
37
+ for (const k in project) {
38
+ if (![
39
+ 'tags',
40
+ 'implicitDependencies',
41
+ 'generators',
42
+ 'targets',
43
+ 'metadata',
44
+ 'namedInputs',
45
+ ].includes(k)) {
46
+ updatedProjectConfiguration[k] = project[k];
47
+ if (sourceMap) {
48
+ sourceMap[`${k}`] = sourceInformation;
49
+ }
40
50
  }
41
51
  }
42
52
  // The next blocks handle properties that should be themselves merged (e.g. targets, tags, and implicit dependencies)
43
53
  if (project.tags) {
44
54
  updatedProjectConfiguration.tags = Array.from(new Set((matchingProject.tags ?? []).concat(project.tags)));
45
55
  if (sourceMap) {
56
+ sourceMap['tags'] ??= sourceInformation;
46
57
  project.tags.forEach((tag) => {
47
58
  sourceMap[`tags.${tag}`] = sourceInformation;
48
59
  });
@@ -51,6 +62,7 @@ skipCommandNormalization) {
51
62
  if (project.implicitDependencies) {
52
63
  updatedProjectConfiguration.implicitDependencies = (matchingProject.implicitDependencies ?? []).concat(project.implicitDependencies);
53
64
  if (sourceMap) {
65
+ sourceMap['implicitDependencies'] ??= sourceInformation;
54
66
  project.implicitDependencies.forEach((implicitDependency) => {
55
67
  sourceMap[`implicitDependencies.${implicitDependency}`] =
56
68
  sourceInformation;
@@ -61,6 +73,7 @@ skipCommandNormalization) {
61
73
  // Start with generators config in new project.
62
74
  updatedProjectConfiguration.generators = { ...project.generators };
63
75
  if (sourceMap) {
76
+ sourceMap['generators'] ??= sourceInformation;
64
77
  for (const generator in project.generators) {
65
78
  sourceMap[`generators.${generator}`] = sourceInformation;
66
79
  for (const property in project.generators[generator]) {
@@ -85,6 +98,7 @@ skipCommandNormalization) {
85
98
  ...project.namedInputs,
86
99
  };
87
100
  if (sourceMap) {
101
+ sourceMap['namedInputs'] ??= sourceInformation;
88
102
  for (const namedInput in project.namedInputs) {
89
103
  sourceMap[`namedInputs.${namedInput}`] = sourceInformation;
90
104
  }
@@ -94,6 +108,9 @@ skipCommandNormalization) {
94
108
  // We merge the targets with special handling, so clear this back to the
95
109
  // targets as defined originally before merging.
96
110
  updatedProjectConfiguration.targets = matchingProject?.targets ?? {};
111
+ if (sourceMap) {
112
+ sourceMap['targets'] ??= sourceInformation;
113
+ }
97
114
  // For each target defined in the new config
98
115
  for (const targetName in project.targets) {
99
116
  // Always set source map info for the target, but don't overwrite info already there
@@ -117,31 +134,102 @@ skipCommandNormalization) {
117
134
  updatedProjectConfiguration.targets[targetName] = mergedTarget;
118
135
  }
119
136
  }
137
+ if (project.metadata) {
138
+ if (sourceMap) {
139
+ sourceMap['targets'] ??= sourceInformation;
140
+ }
141
+ for (const [metadataKey, value] of Object.entries({
142
+ ...project.metadata,
143
+ })) {
144
+ const existingValue = matchingProject.metadata?.[metadataKey];
145
+ if (Array.isArray(value) && Array.isArray(existingValue)) {
146
+ for (const item of [...value]) {
147
+ const newLength = updatedProjectConfiguration.metadata[metadataKey].push(item);
148
+ if (sourceMap) {
149
+ sourceMap[`metadata.${metadataKey}.${newLength - 1}`] =
150
+ sourceInformation;
151
+ }
152
+ }
153
+ }
154
+ else if (Array.isArray(value) && existingValue === undefined) {
155
+ updatedProjectConfiguration.metadata ??= {};
156
+ updatedProjectConfiguration.metadata[metadataKey] ??= value;
157
+ if (sourceMap) {
158
+ sourceMap[`metadata.${metadataKey}`] = sourceInformation;
159
+ }
160
+ for (let i = 0; i < value.length; i++) {
161
+ if (sourceMap) {
162
+ sourceMap[`metadata.${metadataKey}.${i}`] = sourceInformation;
163
+ }
164
+ }
165
+ }
166
+ else if (typeof value === 'object' &&
167
+ typeof existingValue === 'object') {
168
+ for (const key in value) {
169
+ const existingValue = matchingProject.metadata?.[metadataKey]?.[key];
170
+ if (Array.isArray(value[key]) && Array.isArray(existingValue)) {
171
+ for (const item of value[key]) {
172
+ const i = updatedProjectConfiguration.metadata[metadataKey][key].push(item);
173
+ if (sourceMap) {
174
+ sourceMap[`metadata.${metadataKey}.${key}.${i - 1}`] =
175
+ sourceInformation;
176
+ }
177
+ }
178
+ }
179
+ else {
180
+ updatedProjectConfiguration.metadata[metadataKey] = value;
181
+ if (sourceMap) {
182
+ sourceMap[`metadata.${metadataKey}`] = sourceInformation;
183
+ }
184
+ }
185
+ }
186
+ }
187
+ else {
188
+ updatedProjectConfiguration.metadata[metadataKey] = value;
189
+ if (sourceMap) {
190
+ sourceMap[`metadata.${metadataKey}`] = sourceInformation;
191
+ if (typeof value === 'object') {
192
+ for (const k in value) {
193
+ sourceMap[`metadata.${metadataKey}.${k}`] = sourceInformation;
194
+ if (Array.isArray(value[k])) {
195
+ for (let i = 0; i < value[k].length; i++) {
196
+ sourceMap[`metadata.${metadataKey}.${k}.${i}`] =
197
+ sourceInformation;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
120
206
  projectRootMap.set(updatedProjectConfiguration.root, updatedProjectConfiguration);
121
207
  }
122
208
  exports.mergeProjectConfigurationIntoRootMap = mergeProjectConfigurationIntoRootMap;
123
209
  /**
124
210
  * Transforms a list of project paths into a map of project configurations.
125
211
  *
212
+ * @param root The workspace root
126
213
  * @param nxJson The NxJson configuration
127
214
  * @param workspaceFiles A list of non-ignored workspace files
128
215
  * @param plugins The plugins that should be used to infer project configuration
129
- * @param root The workspace root
130
216
  */
131
- function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson, workspaceFiles, // making this parameter allows devkit to pick up newly created projects
132
- plugins, root = workspace_root_1.workspaceRoot) {
217
+ function createProjectConfigurations(root = workspace_root_1.workspaceRoot, nxJson, workspaceFiles, // making this parameter allows devkit to pick up newly created projects
218
+ plugins) {
219
+ perf_hooks_1.performance.mark('build-project-configs:start');
133
220
  const results = [];
221
+ const errors = [];
134
222
  // We iterate over plugins first - this ensures that plugins specified first take precedence.
135
223
  for (const { plugin, options } of plugins) {
136
224
  const [pattern, createNodes] = plugin.createNodes ?? [];
137
225
  const pluginResults = [];
138
- performance.mark(`${plugin.name}:createNodes - start`);
226
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes - start`);
139
227
  if (!pattern) {
140
228
  continue;
141
229
  }
142
230
  const matchingConfigFiles = workspaceFiles.filter(minimatch_1.minimatch.filter(pattern, { dot: true }));
143
231
  for (const file of matchingConfigFiles) {
144
- performance.mark(`${plugin.name}:createNodes:${file} - start`);
232
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes:${file} - start`);
145
233
  try {
146
234
  let r = createNodes(file, options, {
147
235
  nxJsonConfiguration: nxJson,
@@ -150,19 +238,26 @@ plugins, root = workspace_root_1.workspaceRoot) {
150
238
  });
151
239
  if (r instanceof Promise) {
152
240
  pluginResults.push(r
153
- .catch((e) => {
154
- performance.mark(`${plugin.name}:createNodes:${file} - end`);
155
- throw new CreateNodesError(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
241
+ .catch((error) => {
242
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes:${file} - end`);
243
+ errors.push(new CreateNodesError({
244
+ file,
245
+ pluginName: plugin.name,
246
+ error,
247
+ }));
248
+ return {
249
+ projects: {},
250
+ };
156
251
  })
157
252
  .then((r) => {
158
- performance.mark(`${plugin.name}:createNodes:${file} - end`);
159
- performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
253
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes:${file} - end`);
254
+ perf_hooks_1.performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
160
255
  return { ...r, file, pluginName: plugin.name };
161
256
  }));
162
257
  }
163
258
  else {
164
- performance.mark(`${plugin.name}:createNodes:${file} - end`);
165
- performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
259
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes:${file} - end`);
260
+ perf_hooks_1.performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
166
261
  pluginResults.push({
167
262
  ...r,
168
263
  file,
@@ -170,19 +265,22 @@ plugins, root = workspace_root_1.workspaceRoot) {
170
265
  });
171
266
  }
172
267
  }
173
- catch (e) {
174
- throw new CreateNodesError(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
268
+ catch (error) {
269
+ errors.push(new CreateNodesError({
270
+ file,
271
+ pluginName: plugin.name,
272
+ error,
273
+ }));
175
274
  }
176
275
  }
177
- // If there are no promises (counter undefined) or all promises have resolved (counter === 0)
178
276
  results.push(Promise.all(pluginResults).then((results) => {
179
- performance.mark(`${plugin.name}:createNodes - end`);
180
- performance.measure(`${plugin.name}:createNodes`, `${plugin.name}:createNodes - start`, `${plugin.name}:createNodes - end`);
277
+ perf_hooks_1.performance.mark(`${plugin.name}:createNodes - end`);
278
+ perf_hooks_1.performance.measure(`${plugin.name}:createNodes`, `${plugin.name}:createNodes - start`, `${plugin.name}:createNodes - end`);
181
279
  return results;
182
280
  }));
183
281
  }
184
282
  return Promise.all(results).then((results) => {
185
- performance.mark('createNodes:merge - start');
283
+ perf_hooks_1.performance.mark('createNodes:merge - start');
186
284
  const projectRootMap = new Map();
187
285
  const externalNodes = {};
188
286
  const configurationSourceMaps = {};
@@ -200,25 +298,41 @@ plugins, root = workspace_root_1.workspaceRoot) {
200
298
  try {
201
299
  mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInfo);
202
300
  }
203
- catch (e) {
204
- throw new CreateNodesError(`Unable to merge project information for "${project.root}" from ${result.file} using plugin ${result.pluginName}.`, e);
301
+ catch (error) {
302
+ errors.push(new MergeNodesError({
303
+ file,
304
+ pluginName,
305
+ error,
306
+ }));
205
307
  }
206
308
  }
207
309
  Object.assign(externalNodes, pluginExternalNodes);
208
310
  }
209
311
  const projects = readProjectConfigurationsFromRootMap(projectRootMap);
210
312
  const rootMap = createRootMap(projectRootMap);
211
- performance.mark('createNodes:merge - end');
212
- performance.measure('createNodes:merge', 'createNodes:merge - start', 'createNodes:merge - end');
213
- return {
214
- projects,
215
- externalNodes,
216
- rootMap,
217
- sourceMaps: configurationSourceMaps,
218
- };
313
+ perf_hooks_1.performance.mark('createNodes:merge - end');
314
+ perf_hooks_1.performance.measure('createNodes:merge', 'createNodes:merge - start', 'createNodes:merge - end');
315
+ perf_hooks_1.performance.mark('build-project-configs:end');
316
+ perf_hooks_1.performance.measure('build-project-configs', 'build-project-configs:start', 'build-project-configs:end');
317
+ if (errors.length === 0) {
318
+ return {
319
+ projects,
320
+ externalNodes,
321
+ projectRootMap: rootMap,
322
+ sourceMaps: configurationSourceMaps,
323
+ };
324
+ }
325
+ else {
326
+ throw new ProjectConfigurationsError(errors, {
327
+ projects,
328
+ externalNodes,
329
+ projectRootMap: rootMap,
330
+ sourceMaps: configurationSourceMaps,
331
+ });
332
+ }
219
333
  });
220
334
  }
221
- exports.buildProjectsConfigurationsFromProjectPathsAndPlugins = buildProjectsConfigurationsFromProjectPathsAndPlugins;
335
+ exports.createProjectConfigurations = createProjectConfigurations;
222
336
  function readProjectConfigurationsFromRootMap(projectRootMap) {
223
337
  const projects = {};
224
338
  // If there are projects that have the same name, that is an error.
@@ -261,20 +375,37 @@ function readProjectConfigurationsFromRootMap(projectRootMap) {
261
375
  return projects;
262
376
  }
263
377
  exports.readProjectConfigurationsFromRootMap = readProjectConfigurationsFromRootMap;
378
+ class ProjectConfigurationsError extends Error {
379
+ constructor(errors, partialProjectConfigurationsResult) {
380
+ super('Failed to create project configurations');
381
+ this.errors = errors;
382
+ this.partialProjectConfigurationsResult = partialProjectConfigurationsResult;
383
+ this.name = this.constructor.name;
384
+ }
385
+ }
386
+ exports.ProjectConfigurationsError = ProjectConfigurationsError;
264
387
  class CreateNodesError extends Error {
265
- constructor(msg, cause) {
266
- const message = `${msg} ${!cause
267
- ? ''
268
- : cause instanceof Error
269
- ? `\n\n\t Inner Error: ${cause.stack}`
270
- : cause}`;
271
- // These errors are thrown during a JS callback which is invoked via rust.
272
- // The errors messaging gets lost in the rust -> js -> rust transition, but
273
- // logging the error here will ensure that it is visible in the console.
274
- console.error(message);
275
- super(message, { cause });
388
+ constructor({ file, pluginName, error, }) {
389
+ const msg = `The "${pluginName}" plugin threw an error while creating nodes from ${file}:`;
390
+ super(msg, { cause: error });
391
+ this.name = this.constructor.name;
392
+ this.file = file;
393
+ this.pluginName = pluginName;
394
+ this.stack = `${this.message}\n ${error.stack.split('\n').join('\n ')}`;
395
+ }
396
+ }
397
+ exports.CreateNodesError = CreateNodesError;
398
+ class MergeNodesError extends Error {
399
+ constructor({ file, pluginName, error, }) {
400
+ const msg = `The nodes created from ${file} by the "${pluginName}" could not be merged into the project graph:`;
401
+ super(msg, { cause: error });
402
+ this.name = this.constructor.name;
403
+ this.file = file;
404
+ this.pluginName = pluginName;
405
+ this.stack = `${this.message}\n ${error.stack.split('\n').join('\n ')}`;
276
406
  }
277
407
  }
408
+ exports.MergeNodesError = MergeNodesError;
278
409
  /**
279
410
  * Merges two targets.
280
411
  *
@@ -1,7 +1,6 @@
1
1
  import { ProjectConfiguration } from '../../config/workspace-json-project-json';
2
2
  import { NxJsonConfiguration } from '../../config/nx-json';
3
- import { ProjectGraphExternalNode } from '../../config/project-graph';
4
- import { ConfigurationSourceMaps } from './project-configuration-utils';
3
+ import { ConfigurationResult } from './project-configuration-utils';
5
4
  import { LoadedNxPlugin } from '../../utils/nx-plugin';
6
5
  /**
7
6
  * Walks the workspace directory to create the `projectFileMap`, `ProjectConfigurations` and `allWorkspaceFiles`
@@ -10,12 +9,12 @@ import { LoadedNxPlugin } from '../../utils/nx-plugin';
10
9
  * @param nxJson
11
10
  */
12
11
  export declare function retrieveWorkspaceFiles(workspaceRoot: string, projectRootMap: Record<string, string>): Promise<{
13
- allWorkspaceFiles: import("../../config/project-graph").FileData[];
12
+ allWorkspaceFiles: import("nx/src/devkit-exports").FileData[];
14
13
  fileMap: {
15
14
  projectFileMap: ProjectFiles;
16
- nonProjectFiles: import("../../native").FileData[];
15
+ nonProjectFiles: import("nx/src/native").FileData[];
17
16
  };
18
- rustReferences: import("../../native").NxWorkspaceFilesExternals;
17
+ rustReferences: import("nx/src/native").NxWorkspaceFilesExternals;
19
18
  }>;
20
19
  /**
21
20
  * Walk through the workspace and return `ProjectConfigurations`. Only use this if the projectFileMap is not needed.
@@ -23,15 +22,8 @@ export declare function retrieveWorkspaceFiles(workspaceRoot: string, projectRoo
23
22
  * @param workspaceRoot
24
23
  * @param nxJson
25
24
  */
26
- export declare function retrieveProjectConfigurations(workspaceRoot: string, nxJson: NxJsonConfiguration): Promise<RetrievedGraphNodes>;
27
- export declare function retrieveProjectConfigurationsWithAngularProjects(workspaceRoot: string, nxJson: NxJsonConfiguration): Promise<RetrievedGraphNodes>;
28
- export type RetrievedGraphNodes = {
29
- externalNodes: Record<string, ProjectGraphExternalNode>;
30
- projects: Record<string, ProjectConfiguration>;
31
- sourceMaps: ConfigurationSourceMaps;
32
- projectRootMap: Record<string, string>;
33
- };
25
+ export declare function retrieveProjectConfigurations(workspaceRoot: string, nxJson: NxJsonConfiguration): Promise<ConfigurationResult>;
26
+ export declare function retrieveProjectConfigurationsWithAngularProjects(workspaceRoot: string, nxJson: NxJsonConfiguration): Promise<ConfigurationResult>;
34
27
  export declare function retrieveProjectConfigurationPaths(root: string, plugins: LoadedNxPlugin[]): string[];
35
28
  export declare function retrieveProjectConfigurationsWithoutPluginInference(root: string): Promise<Record<string, ProjectConfiguration>>;
36
- export declare function createProjectConfigurations(workspaceRoot: string, nxJson: NxJsonConfiguration, configFiles: string[], plugins: LoadedNxPlugin[]): Promise<RetrievedGraphNodes>;
37
29
  export declare function configurationGlobs(plugins: LoadedNxPlugin[]): string[];