nx 18.3.2 → 18.3.4

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 (42) hide show
  1. package/migrations.json +2 -1
  2. package/package.json +12 -12
  3. package/src/command-line/graph/command-object.js +1 -1
  4. package/src/command-line/show/command-object.js +1 -5
  5. package/src/command-line/yargs-utils/shared-options.d.ts +3 -0
  6. package/src/command-line/yargs-utils/shared-options.js +15 -6
  7. package/src/core/graph/main.js +1 -1
  8. package/src/daemon/server/project-graph-incremental-recomputation.js +6 -6
  9. package/src/daemon/server/server.js +1 -4
  10. package/src/daemon/socket-utils.js +2 -14
  11. package/src/devkit-internals.d.ts +1 -0
  12. package/src/devkit-internals.js +3 -1
  13. package/src/executors/run-commands/run-commands.impl.d.ts +1 -0
  14. package/src/executors/run-commands/run-commands.impl.js +64 -12
  15. package/src/executors/run-commands/schema.json +5 -0
  16. package/src/executors/utils/convert-nx-executor.js +2 -1
  17. package/src/generators/utils/project-configuration.js +2 -2
  18. package/src/project-graph/build-project-graph.d.ts +1 -1
  19. package/src/project-graph/build-project-graph.js +7 -8
  20. package/src/project-graph/error-types.d.ts +5 -1
  21. package/src/project-graph/error-types.js +11 -1
  22. package/src/project-graph/file-utils.js +1 -1
  23. package/src/project-graph/plugins/isolation/messaging.d.ts +9 -6
  24. package/src/project-graph/plugins/isolation/messaging.js +27 -10
  25. package/src/project-graph/plugins/isolation/plugin-pool.js +11 -14
  26. package/src/project-graph/plugins/isolation/plugin-worker.js +21 -5
  27. package/src/project-graph/plugins/loader.js +35 -23
  28. package/src/project-graph/plugins/public-api.d.ts +1 -1
  29. package/src/project-graph/plugins/utils.d.ts +2 -2
  30. package/src/project-graph/plugins/utils.js +15 -16
  31. package/src/project-graph/utils/find-project-for-path.js +2 -3
  32. package/src/project-graph/utils/normalize-project-nodes.d.ts +1 -1
  33. package/src/project-graph/utils/normalize-project-nodes.js +8 -8
  34. package/src/project-graph/utils/project-configuration-utils.d.ts +18 -3
  35. package/src/project-graph/utils/project-configuration-utils.js +22 -14
  36. package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
  37. package/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.js +4 -0
  38. package/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.js +4 -0
  39. package/src/tasks-runner/pseudo-terminal.js +6 -0
  40. package/src/utils/perf-logging.js +3 -1
  41. package/src/utils/serializable-error.d.ts +4 -0
  42. package/src/utils/serializable-error.js +28 -0
@@ -142,22 +142,22 @@ async function processFilesAndCreateAndSerializeProjectGraph(plugins) {
142
142
  logger_1.serverLogger.requestLog([...deletedFiles]);
143
143
  const nxJson = (0, nx_json_1.readNxJson)(workspace_root_1.workspaceRoot);
144
144
  global.NX_GRAPH_CREATION = true;
145
- let graphNodes;
145
+ let projectConfigurationsResult;
146
146
  let projectConfigurationsError;
147
147
  try {
148
- graphNodes = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, workspace_root_1.workspaceRoot, nxJson);
148
+ projectConfigurationsResult = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, workspace_root_1.workspaceRoot, nxJson);
149
149
  }
150
150
  catch (e) {
151
151
  if (e instanceof error_types_1.ProjectConfigurationsError) {
152
- graphNodes = e.partialProjectConfigurationsResult;
152
+ projectConfigurationsResult = e.partialProjectConfigurationsResult;
153
153
  projectConfigurationsError = e;
154
154
  }
155
155
  else {
156
156
  throw e;
157
157
  }
158
158
  }
159
- await processCollectedUpdatedAndDeletedFiles(graphNodes, updatedFileHashes, deletedFiles);
160
- const g = await createAndSerializeProjectGraph(graphNodes);
159
+ await processCollectedUpdatedAndDeletedFiles(projectConfigurationsResult, updatedFileHashes, deletedFiles);
160
+ const g = await createAndSerializeProjectGraph(projectConfigurationsResult);
161
161
  delete global.NX_GRAPH_CREATION;
162
162
  const errors = [...(projectConfigurationsError?.errors ?? [])];
163
163
  if (g.error) {
@@ -179,7 +179,7 @@ async function processFilesAndCreateAndSerializeProjectGraph(plugins) {
179
179
  }
180
180
  if (errors.length > 0) {
181
181
  return {
182
- error: new error_types_1.DaemonProjectGraphError(errors, g.projectGraph, graphNodes.sourceMaps),
182
+ error: new error_types_1.DaemonProjectGraphError(errors, g.projectGraph, projectConfigurationsResult.sourceMaps),
183
183
  projectGraph: null,
184
184
  projectFileMapCache: null,
185
185
  fileMap: null,
@@ -60,10 +60,7 @@ async function handleMessage(socket, data) {
60
60
  await (0, shutdown_utils_1.respondWithErrorAndExit)(socket, `File watcher error in the workspace '${workspace_root_1.workspaceRoot}'.`, workspaceWatcherError);
61
61
  }
62
62
  if (daemonIsOutdated()) {
63
- await (0, shutdown_utils_1.respondWithErrorAndExit)(socket, `Lock files changed`, {
64
- name: '',
65
- message: 'LOCK-FILES-CHANGED',
66
- });
63
+ await (0, shutdown_utils_1.respondWithErrorAndExit)(socket, `Lock files changed`, new Error('LOCK-FILES-CHANGED'));
67
64
  }
68
65
  (0, shutdown_utils_1.resetInactivityTimeout)(handleInactivityTimeout);
69
66
  const unparsedPayload = data;
@@ -5,7 +5,7 @@ const fs_1 = require("fs");
5
5
  const os_1 = require("os");
6
6
  const path_1 = require("path");
7
7
  const tmp_dir_1 = require("./tmp-dir");
8
- const error_types_1 = require("../project-graph/error-types");
8
+ const serializable_error_1 = require("../utils/serializable-error");
9
9
  exports.isWindows = (0, os_1.platform)() === 'win32';
10
10
  /**
11
11
  * For IPC with the daemon server we use unix sockets or windows named pipes, depending on the user's operating system.
@@ -28,21 +28,9 @@ function killSocketOrPath() {
28
28
  catch { }
29
29
  }
30
30
  exports.killSocketOrPath = killSocketOrPath;
31
- // Include the original stack trace within the serialized error so that the client can show it to the user.
32
- function serializeError(error) {
33
- if (!error) {
34
- return null;
35
- }
36
- if (error instanceof error_types_1.DaemonProjectGraphError) {
37
- error.errors = error.errors.map((e) => JSON.parse(serializeError(e)));
38
- }
39
- return `{${Object.getOwnPropertyNames(error)
40
- .map((k) => `"${k}": ${JSON.stringify(error[k])}`)
41
- .join(',')}}`;
42
- }
43
31
  // Prepare a serialized project graph result for sending over IPC from the server to the client
44
32
  function serializeResult(error, serializedProjectGraph, serializedSourceMaps) {
45
33
  // We do not want to repeat work `JSON.stringify`ing an object containing the potentially large project graph so merge as strings
46
- return `{ "error": ${serializeError(error)}, "projectGraph": ${serializedProjectGraph}, "sourceMaps": ${serializedSourceMaps} }`;
34
+ return `{ "error": ${JSON.stringify(error ? (0, serializable_error_1.createSerializableError)(error) : error)}, "projectGraph": ${serializedProjectGraph}, "sourceMaps": ${serializedSourceMaps} }`;
47
35
  }
48
36
  exports.serializeResult = serializeResult;
@@ -8,6 +8,7 @@ export { getExecutorInformation } from './command-line/run/executor-utils';
8
8
  export { readNxJson as readNxJsonFromDisk } from './config/nx-json';
9
9
  export { calculateDefaultProjectName } from './config/calculate-default-project-name';
10
10
  export { retrieveProjectConfigurationsWithAngularProjects } from './project-graph/utils/retrieve-workspace-files';
11
+ export { readProjectConfigurationsFromRootMap } from './project-graph/utils/project-configuration-utils';
11
12
  export { splitTarget } from './utils/split-target';
12
13
  export { combineOptionsForExecutor } from './utils/params';
13
14
  export { sortObjectByKeys } from './utils/object-sort';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
3
+ exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.readProjectConfigurationsFromRootMap = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  /**
6
6
  * Note to developers: STOP! These exports are available via requireNx in @nx/devkit.
@@ -17,6 +17,8 @@ var calculate_default_project_name_1 = require("./config/calculate-default-proje
17
17
  Object.defineProperty(exports, "calculateDefaultProjectName", { enumerable: true, get: function () { return calculate_default_project_name_1.calculateDefaultProjectName; } });
18
18
  var retrieve_workspace_files_1 = require("./project-graph/utils/retrieve-workspace-files");
19
19
  Object.defineProperty(exports, "retrieveProjectConfigurationsWithAngularProjects", { enumerable: true, get: function () { return retrieve_workspace_files_1.retrieveProjectConfigurationsWithAngularProjects; } });
20
+ var project_configuration_utils_1 = require("./project-graph/utils/project-configuration-utils");
21
+ Object.defineProperty(exports, "readProjectConfigurationsFromRootMap", { enumerable: true, get: function () { return project_configuration_utils_1.readProjectConfigurationsFromRootMap; } });
20
22
  var split_target_1 = require("./utils/split-target");
21
23
  Object.defineProperty(exports, "splitTarget", { enumerable: true, get: function () { return split_target_1.splitTarget; } });
22
24
  var params_1 = require("./utils/params");
@@ -22,6 +22,7 @@ export interface RunCommandsOptions extends Json {
22
22
  readyWhen?: string;
23
23
  cwd?: string;
24
24
  env?: Record<string, string>;
25
+ forwardAllArgs?: boolean;
25
26
  args?: string | string[];
26
27
  envFile?: string;
27
28
  __unparsed__: string[];
@@ -7,7 +7,10 @@ const yargsParser = require("yargs-parser");
7
7
  const npm_run_path_1 = require("npm-run-path");
8
8
  const chalk = require("chalk");
9
9
  const pseudo_terminal_1 = require("../../tasks-runner/pseudo-terminal");
10
+ const exit_codes_1 = require("../../utils/exit-codes");
10
11
  exports.LARGE_BUFFER = 1024 * 1000000;
12
+ let pseudoTerminal;
13
+ const childProcesses = new Set();
11
14
  async function loadEnvVars(path) {
12
15
  if (path) {
13
16
  const result = (await Promise.resolve().then(() => require('dotenv'))).config({ path });
@@ -36,8 +39,10 @@ const propKeys = [
36
39
  'usePty',
37
40
  'streamOutput',
38
41
  'verbose',
42
+ 'forwardAllArgs',
39
43
  ];
40
44
  async function default_1(options, context) {
45
+ registerProcessListener();
41
46
  await loadEnvVars(options.envFile);
42
47
  const normalized = normalizeOptions(options);
43
48
  if (options.readyWhen && !options.parallel) {
@@ -131,14 +136,12 @@ function normalizeOptions(options) {
131
136
  options.parsedArgs = parseArgs(unparsedCommandArgs, options.unknownOptions, options.args);
132
137
  options.unparsedCommandArgs = unparsedCommandArgs;
133
138
  options.commands.forEach((c) => {
134
- c.command = interpolateArgsIntoCommand(c.command, options, c.forwardAllArgs ?? true);
139
+ c.command = interpolateArgsIntoCommand(c.command, options, c.forwardAllArgs ?? options.forwardAllArgs ?? true);
135
140
  });
136
141
  return options;
137
142
  }
138
143
  async function runSerially(options, context) {
139
- const pseudoTerminal = pseudo_terminal_1.PseudoTerminal.isSupported()
140
- ? (0, pseudo_terminal_1.getPseudoTerminal)()
141
- : null;
144
+ pseudoTerminal ??= pseudo_terminal_1.PseudoTerminal.isSupported() ? (0, pseudo_terminal_1.getPseudoTerminal)() : null;
142
145
  let terminalOutput = '';
143
146
  for (const c of options.commands) {
144
147
  const result = await createProcess(pseudoTerminal, c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
@@ -172,6 +175,7 @@ async function createProcess(pseudoTerminal, commandConfig, readyWhen, color, cw
172
175
  jsEnv: env,
173
176
  quiet: !streamOutput,
174
177
  });
178
+ childProcesses.add(cp);
175
179
  return new Promise((res) => {
176
180
  cp.onOutput((output) => {
177
181
  terminalOutput += output;
@@ -202,14 +206,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
202
206
  env,
203
207
  cwd,
204
208
  });
205
- /**
206
- * Ensure the child process is killed when the parent exits
207
- */
208
- const processExitListener = (signal) => childProcess.kill(signal);
209
- process.on('exit', processExitListener);
210
- process.on('SIGTERM', processExitListener);
211
- process.on('SIGINT', processExitListener);
212
- process.on('SIGQUIT', processExitListener);
209
+ childProcesses.add(childProcess);
213
210
  childProcess.stdout.on('data', (data) => {
214
211
  const output = addColorAndPrefix(data, commandConfig);
215
212
  terminalOutput += output;
@@ -239,6 +236,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
239
236
  res({ success: false, terminalOutput });
240
237
  });
241
238
  childProcess.on('exit', (code) => {
239
+ childProcesses.delete(childProcess);
242
240
  if (!readyWhen) {
243
241
  res({ success: code === 0, terminalOutput });
244
242
  }
@@ -361,3 +359,57 @@ function filterPropKeysFromUnParsedOptions(__unparsed__, unparsedCommandArgs = {
361
359
  }
362
360
  return parsedOptions;
363
361
  }
362
+ let registered = false;
363
+ function registerProcessListener() {
364
+ if (registered) {
365
+ return;
366
+ }
367
+ registered = true;
368
+ // When the nx process gets a message, it will be sent into the task's process
369
+ process.on('message', (message) => {
370
+ // this.publisher.publish(message.toString());
371
+ if (pseudoTerminal) {
372
+ pseudoTerminal.sendMessageToChildren(message);
373
+ }
374
+ childProcesses.forEach((p) => {
375
+ if ('connected' in p && p.connected) {
376
+ p.send(message);
377
+ }
378
+ });
379
+ });
380
+ // Terminate any task processes on exit
381
+ process.on('exit', () => {
382
+ childProcesses.forEach((p) => {
383
+ if ('connected' in p ? p.connected : p.isAlive) {
384
+ p.kill();
385
+ }
386
+ });
387
+ });
388
+ process.on('SIGINT', () => {
389
+ childProcesses.forEach((p) => {
390
+ if ('connected' in p ? p.connected : p.isAlive) {
391
+ p.kill('SIGTERM');
392
+ }
393
+ });
394
+ // we exit here because we don't need to write anything to cache.
395
+ process.exit((0, exit_codes_1.signalToCode)('SIGINT'));
396
+ });
397
+ process.on('SIGTERM', () => {
398
+ childProcesses.forEach((p) => {
399
+ if ('connected' in p ? p.connected : p.isAlive) {
400
+ p.kill('SIGTERM');
401
+ }
402
+ });
403
+ // no exit here because we expect child processes to terminate which
404
+ // will store results to the cache and will terminate this process
405
+ });
406
+ process.on('SIGHUP', () => {
407
+ childProcesses.forEach((p) => {
408
+ if ('connected' in p ? p.connected : p.isAlive) {
409
+ p.kill('SIGTERM');
410
+ }
411
+ });
412
+ // no exit here because we expect child processes to terminate which
413
+ // will store results to the cache and will terminate this process
414
+ });
415
+ }
@@ -135,6 +135,11 @@
135
135
  "$source": "unparsed"
136
136
  },
137
137
  "x-priority": "internal"
138
+ },
139
+ "forwardAllArgs": {
140
+ "type": "boolean",
141
+ "description": "Whether arguments should be forwarded when interpolation is not present.",
142
+ "default": true
138
143
  }
139
144
  },
140
145
  "additionalProperties": true,
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.convertNxExecutor = void 0;
7
7
  const nx_json_1 = require("../../config/nx-json");
8
8
  const retrieve_workspace_files_1 = require("../../project-graph/utils/retrieve-workspace-files");
9
+ const project_configuration_utils_1 = require("../../project-graph/utils/project-configuration-utils");
9
10
  const internal_api_1 = require("../../project-graph/plugins/internal-api");
10
11
  /**
11
12
  * Convert an Nx Executor into an Angular Devkit Builder
@@ -19,7 +20,7 @@ function convertNxExecutor(executor) {
19
20
  const [plugins, cleanup] = await (0, internal_api_1.loadNxPlugins)(nxJsonConfiguration.plugins, builderContext.workspaceRoot);
20
21
  const projectsConfigurations = {
21
22
  version: 2,
22
- projects: (await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, builderContext.workspaceRoot, nxJsonConfiguration)).projects,
23
+ projects: (0, project_configuration_utils_1.readProjectConfigurationsFromRootMap)((await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, builderContext.workspaceRoot, nxJsonConfiguration)).projects),
23
24
  };
24
25
  cleanup();
25
26
  const context = {
@@ -143,7 +143,7 @@ function readAndCombineAllProjectConfigurations(tree) {
143
143
  const createdFiles = findCreatedProjectFiles(tree, patterns);
144
144
  const deletedFiles = findDeletedProjectFiles(tree, patterns);
145
145
  const projectFiles = [...globbedFiles, ...createdFiles].filter((r) => deletedFiles.indexOf(r) === -1);
146
- const rootMap = new Map();
146
+ const rootMap = {};
147
147
  for (const projectFile of projectFiles) {
148
148
  if ((0, path_1.basename)(projectFile) === 'project.json') {
149
149
  const json = (0, json_1.readJson)(tree, projectFile);
@@ -153,7 +153,7 @@ function readAndCombineAllProjectConfigurations(tree) {
153
153
  else if ((0, path_1.basename)(projectFile) === 'package.json') {
154
154
  const packageJson = (0, json_1.readJson)(tree, projectFile);
155
155
  const config = (0, package_json_workspaces_1.buildProjectConfigurationFromPackageJson)(packageJson, projectFile, (0, nx_json_1.readNxJson)(tree));
156
- if (!rootMap.has(config.root)) {
156
+ if (!rootMap[config.root]) {
157
157
  (0, project_configuration_utils_1.mergeProjectConfigurationIntoRootMap)(rootMap,
158
158
  // Inferred targets, tags, etc don't show up when running generators
159
159
  // This is to help avoid running into issues when trying to update the workspace
@@ -9,7 +9,7 @@ export declare function getFileMap(): {
9
9
  allWorkspaceFiles: FileData[];
10
10
  rustReferences: NxWorkspaceFilesExternals | null;
11
11
  };
12
- export declare function buildProjectGraphUsingProjectFileMap(projects: Record<string, ProjectConfiguration>, externalNodes: Record<string, ProjectGraphExternalNode>, fileMap: FileMap, allWorkspaceFiles: FileData[], rustReferences: NxWorkspaceFilesExternals, fileMapCache: FileMapCache | null, plugins: LoadedNxPlugin[]): Promise<{
12
+ export declare function buildProjectGraphUsingProjectFileMap(projectRootMap: Record<string, ProjectConfiguration>, externalNodes: Record<string, ProjectGraphExternalNode>, fileMap: FileMap, allWorkspaceFiles: FileData[], rustReferences: NxWorkspaceFilesExternals, fileMapCache: FileMapCache | null, plugins: LoadedNxPlugin[]): Promise<{
13
13
  projectGraph: ProjectGraph;
14
14
  projectFileMapCache: FileMapCache;
15
15
  }>;
@@ -38,10 +38,15 @@ function getFileMap() {
38
38
  }
39
39
  }
40
40
  exports.getFileMap = getFileMap;
41
- async function buildProjectGraphUsingProjectFileMap(projects, externalNodes, fileMap, allWorkspaceFiles, rustReferences, fileMapCache, plugins) {
41
+ async function buildProjectGraphUsingProjectFileMap(projectRootMap, externalNodes, fileMap, allWorkspaceFiles, rustReferences, fileMapCache, plugins) {
42
42
  storedFileMap = fileMap;
43
43
  storedAllWorkspaceFiles = allWorkspaceFiles;
44
44
  storedRustReferences = rustReferences;
45
+ const projects = {};
46
+ for (const root in projectRootMap) {
47
+ const project = projectRootMap[root];
48
+ projects[project.name] = project;
49
+ }
45
50
  const nxJson = (0, configuration_1.readNxJson)();
46
51
  const projectGraphVersion = '6.0';
47
52
  (0, assert_workspace_validity_1.assertWorkspaceValidity)(projects, nxJson);
@@ -138,15 +143,9 @@ async function buildProjectGraphUsingContext(knownExternalNodes, ctx, cachedFile
138
143
  }
139
144
  }
140
145
  function createContext(projects, nxJson, externalNodes, fileMap, filesToProcess) {
141
- const clonedProjects = Object.keys(projects).reduce((map, projectName) => {
142
- map[projectName] = {
143
- ...projects[projectName],
144
- };
145
- return map;
146
- }, {});
147
146
  return {
148
147
  nxJsonConfiguration: nxJson,
149
- projects: clonedProjects,
148
+ projects,
150
149
  externalNodes,
151
150
  workspaceRoot: workspace_root_1.workspaceRoot,
152
151
  fileMap,
@@ -19,7 +19,7 @@ export declare class ProjectGraphError extends Error {
19
19
  */
20
20
  getPartialProjectGraph(): ProjectGraph;
21
21
  getPartialSourcemaps(): ConfigurationSourceMaps;
22
- getErrors(): (CreateNodesError | MergeNodesError | ProjectsWithNoNameError | ProjectsWithConflictingNamesError | ProcessDependenciesError | ProcessProjectGraphError)[];
22
+ getErrors(): (ProcessDependenciesError | ProcessProjectGraphError | CreateNodesError | MergeNodesError | ProjectsWithNoNameError | ProjectsWithConflictingNamesError)[];
23
23
  }
24
24
  export declare class ProjectsWithConflictingNamesError extends Error {
25
25
  projects: Record<string, ProjectConfiguration>;
@@ -69,3 +69,7 @@ export declare class DaemonProjectGraphError extends Error {
69
69
  readonly sourceMaps: ConfigurationSourceMaps;
70
70
  constructor(errors: any[], projectGraph: ProjectGraph, sourceMaps: ConfigurationSourceMaps);
71
71
  }
72
+ export declare class LoadPluginError extends Error {
73
+ plugin: string;
74
+ constructor(plugin: string, cause: Error);
75
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _ProjectGraphError_errors, _ProjectGraphError_partialProjectGraph, _ProjectGraphError_partialSourceMaps;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DaemonProjectGraphError = exports.isMergeNodesError = exports.isAggregateCreateNodesError = exports.isCreateNodesError = exports.MergeNodesError = exports.AggregateCreateNodesError = exports.CreateNodesError = exports.ProjectConfigurationsError = exports.isProjectsWithNoNameError = exports.ProjectsWithNoNameError = exports.isProjectsWithConflictingNamesError = exports.ProjectsWithConflictingNamesError = exports.ProjectGraphError = void 0;
4
+ exports.LoadPluginError = exports.DaemonProjectGraphError = exports.isMergeNodesError = exports.isAggregateCreateNodesError = exports.isCreateNodesError = exports.MergeNodesError = exports.AggregateCreateNodesError = exports.CreateNodesError = exports.ProjectConfigurationsError = exports.isProjectsWithNoNameError = exports.ProjectsWithNoNameError = exports.isProjectsWithConflictingNamesError = exports.ProjectsWithConflictingNamesError = exports.ProjectGraphError = void 0;
5
5
  const tslib_1 = require("tslib");
6
6
  class ProjectGraphError extends Error {
7
7
  constructor(errors, partialProjectGraph, partialSourceMaps) {
@@ -145,3 +145,13 @@ class DaemonProjectGraphError extends Error {
145
145
  }
146
146
  }
147
147
  exports.DaemonProjectGraphError = DaemonProjectGraphError;
148
+ class LoadPluginError extends Error {
149
+ constructor(plugin, cause) {
150
+ super(`Could not load plugin ${plugin}`, {
151
+ cause,
152
+ });
153
+ this.plugin = plugin;
154
+ this.name = this.constructor.name;
155
+ }
156
+ }
157
+ exports.LoadPluginError = LoadPluginError;
@@ -152,7 +152,7 @@ function getProjectsSyncNoInference(root, nxJson) {
152
152
  package_json_next_to_project_json_1.PackageJsonProjectsNextToProjectJsonPlugin,
153
153
  ...(0, nx_plugin_deprecated_1.getDefaultPluginsSync)(root),
154
154
  ];
155
- const projectRootMap = new Map();
155
+ const projectRootMap = {};
156
156
  // We iterate over plugins first - this ensures that plugins specified first take precedence.
157
157
  for (const plugin of plugins) {
158
158
  const [pattern, createNodes] = plugin.createNodes ?? [];
@@ -1,7 +1,9 @@
1
+ /// <reference types="node" />
1
2
  import { ProjectGraph, ProjectGraphProcessorContext } from '../../../config/project-graph';
2
3
  import { PluginConfiguration } from '../../../config/nx-json';
3
4
  import { CreateDependenciesContext, CreateNodesContext } from '../public-api';
4
5
  import { LoadedNxPlugin } from '../internal-api';
6
+ import { Serializable } from 'child_process';
5
7
  export interface PluginWorkerLoadMessage {
6
8
  type: 'load';
7
9
  payload: {
@@ -19,7 +21,7 @@ export interface PluginWorkerLoadResult {
19
21
  success: true;
20
22
  } | {
21
23
  success: false;
22
- error: string;
24
+ error: Error;
23
25
  };
24
26
  }
25
27
  export interface PluginWorkerCreateNodesMessage {
@@ -38,7 +40,7 @@ export interface PluginWorkerCreateNodesResult {
38
40
  tx: string;
39
41
  } | {
40
42
  success: false;
41
- error: string;
43
+ error: Error;
42
44
  tx: string;
43
45
  };
44
46
  }
@@ -57,7 +59,7 @@ export interface PluginCreateDependenciesResult {
57
59
  tx: string;
58
60
  } | {
59
61
  success: false;
60
- error: string;
62
+ error: Error;
61
63
  tx: string;
62
64
  };
63
65
  }
@@ -77,18 +79,19 @@ export interface PluginWorkerProcessProjectGraphResult {
77
79
  tx: string;
78
80
  } | {
79
81
  success: false;
80
- error: string;
82
+ error: Error;
81
83
  tx: string;
82
84
  };
83
85
  }
84
86
  export type PluginWorkerMessage = PluginWorkerLoadMessage | PluginWorkerCreateNodesMessage | PluginCreateDependenciesMessage | PluginWorkerProcessProjectGraphMessage;
85
87
  export type PluginWorkerResult = PluginWorkerLoadResult | PluginWorkerCreateNodesResult | PluginCreateDependenciesResult | PluginWorkerProcessProjectGraphResult;
88
+ export declare function isPluginWorkerMessage(message: Serializable): message is PluginWorkerMessage;
89
+ export declare function isPluginWorkerResult(message: Serializable): message is PluginWorkerResult;
86
90
  type MaybePromise<T> = T | Promise<T>;
87
91
  type MessageHandlerReturn<T extends PluginWorkerMessage | PluginWorkerResult> = T extends PluginWorkerResult ? MaybePromise<PluginWorkerMessage | void> : MaybePromise<PluginWorkerResult | void>;
88
- export declare function consumeMessage<T extends PluginWorkerMessage | PluginWorkerResult>(raw: string | T, handlers: {
92
+ export declare function consumeMessage<T extends PluginWorkerMessage | PluginWorkerResult>(raw: T, handlers: {
89
93
  [K in T['type']]: (payload: Extract<T, {
90
94
  type: K;
91
95
  }>['payload']) => MessageHandlerReturn<T>;
92
96
  }): Promise<void>;
93
- export declare function createMessage(message: PluginWorkerMessage | PluginWorkerResult): string;
94
97
  export {};
@@ -1,23 +1,40 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createMessage = exports.consumeMessage = void 0;
3
+ exports.consumeMessage = exports.isPluginWorkerResult = exports.isPluginWorkerMessage = void 0;
4
+ function isPluginWorkerMessage(message) {
5
+ return (typeof message === 'object' &&
6
+ 'type' in message &&
7
+ typeof message.type === 'string' &&
8
+ [
9
+ 'load',
10
+ 'createNodes',
11
+ 'createDependencies',
12
+ 'processProjectGraph',
13
+ ].includes(message.type));
14
+ }
15
+ exports.isPluginWorkerMessage = isPluginWorkerMessage;
16
+ function isPluginWorkerResult(message) {
17
+ return (typeof message === 'object' &&
18
+ 'type' in message &&
19
+ typeof message.type === 'string' &&
20
+ [
21
+ 'load-result',
22
+ 'createNodesResult',
23
+ 'createDependenciesResult',
24
+ 'processProjectGraphResult',
25
+ ].includes(message.type));
26
+ }
27
+ exports.isPluginWorkerResult = isPluginWorkerResult;
4
28
  // Takes a message and a map of handlers and calls the appropriate handler
5
29
  // type safe and requires all handlers to be handled
6
30
  async function consumeMessage(raw, handlers) {
7
- const message = typeof raw === 'string' ? JSON.parse(raw) : raw;
31
+ const message = raw;
8
32
  const handler = handlers[message.type];
9
33
  if (handler) {
10
34
  const response = await handler(message.payload);
11
35
  if (response) {
12
- process.send(createMessage(response));
36
+ process.send(response);
13
37
  }
14
38
  }
15
- else {
16
- throw new Error(`Unhandled message type: ${message.type}`);
17
- }
18
39
  }
19
40
  exports.consumeMessage = consumeMessage;
20
- function createMessage(message) {
21
- return JSON.stringify(message);
22
- }
23
- exports.createMessage = createMessage;
@@ -32,7 +32,7 @@ function loadRemoteNxPlugin(plugin, root) {
32
32
  ...(isWorkerTypescript ? ['-r', 'ts-node/register'] : []),
33
33
  ],
34
34
  });
35
- worker.send((0, messaging_1.createMessage)({ type: 'load', payload: { plugin, root } }));
35
+ worker.send({ type: 'load', payload: { plugin, root } });
36
36
  // logger.verbose(`[plugin-worker] started worker: ${worker.pid}`);
37
37
  const pendingPromises = new Map();
38
38
  const exitHandler = createWorkerExitHandler(worker, pendingPromises);
@@ -67,13 +67,10 @@ async function shutdownPluginWorker(worker, pendingPromises) {
67
67
  function createWorkerHandler(worker, pending, onload, onloadError) {
68
68
  let pluginName;
69
69
  return function (message) {
70
- const parsed = JSON.parse(message);
71
- // logger.verbose(
72
- // `[plugin-pool] received message: ${parsed.type} from ${
73
- // pluginName ?? worker.pid
74
- // }`
75
- // );
76
- (0, messaging_1.consumeMessage)(parsed, {
70
+ if (!(0, messaging_1.isPluginWorkerResult)(message)) {
71
+ return;
72
+ }
73
+ return (0, messaging_1.consumeMessage)(message, {
77
74
  'load-result': (result) => {
78
75
  if (result.success) {
79
76
  const { name, createNodesPattern } = result;
@@ -87,10 +84,10 @@ function createWorkerHandler(worker, pending, onload, onloadError) {
87
84
  (configFiles, ctx) => {
88
85
  const tx = pluginName + ':createNodes:' + performance.now();
89
86
  return registerPendingPromise(tx, pending, () => {
90
- worker.send((0, messaging_1.createMessage)({
87
+ worker.send({
91
88
  type: 'createNodes',
92
89
  payload: { configFiles, context: ctx, tx },
93
- }));
90
+ });
94
91
  });
95
92
  },
96
93
  ]
@@ -99,10 +96,10 @@ function createWorkerHandler(worker, pending, onload, onloadError) {
99
96
  ? (ctx) => {
100
97
  const tx = pluginName + ':createDependencies:' + performance.now();
101
98
  return registerPendingPromise(tx, pending, () => {
102
- worker.send((0, messaging_1.createMessage)({
99
+ worker.send({
103
100
  type: 'createDependencies',
104
101
  payload: { context: ctx, tx },
105
- }));
102
+ });
106
103
  });
107
104
  }
108
105
  : undefined,
@@ -110,10 +107,10 @@ function createWorkerHandler(worker, pending, onload, onloadError) {
110
107
  ? (graph, ctx) => {
111
108
  const tx = pluginName + ':processProjectGraph:' + performance.now();
112
109
  return registerPendingPromise(tx, pending, () => {
113
- worker.send((0, messaging_1.createMessage)({
110
+ worker.send({
114
111
  type: 'processProjectGraph',
115
112
  payload: { graph, ctx, tx },
116
- }));
113
+ });
117
114
  });
118
115
  }
119
116
  : undefined,
@@ -2,10 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const messaging_1 = require("./messaging");
4
4
  const loader_1 = require("../loader");
5
+ const serializable_error_1 = require("../../../utils/serializable-error");
5
6
  global.NX_GRAPH_CREATION = true;
6
7
  let plugin;
7
8
  process.on('message', async (message) => {
8
- (0, messaging_1.consumeMessage)(message, {
9
+ if (!(0, messaging_1.isPluginWorkerMessage)(message)) {
10
+ return;
11
+ }
12
+ return (0, messaging_1.consumeMessage)(message, {
9
13
  load: async ({ plugin: pluginConfiguration, root }) => {
10
14
  process.chdir(root);
11
15
  try {
@@ -27,7 +31,7 @@ process.on('message', async (message) => {
27
31
  type: 'load-result',
28
32
  payload: {
29
33
  success: false,
30
- error: `Could not load plugin ${plugin} \n ${e instanceof Error ? e.stack : ''}`,
34
+ error: (0, serializable_error_1.createSerializableError)(e),
31
35
  },
32
36
  };
33
37
  }
@@ -43,7 +47,11 @@ process.on('message', async (message) => {
43
47
  catch (e) {
44
48
  return {
45
49
  type: 'createNodesResult',
46
- payload: { success: false, error: e.stack, tx },
50
+ payload: {
51
+ success: false,
52
+ error: (0, serializable_error_1.createSerializableError)(e),
53
+ tx,
54
+ },
47
55
  };
48
56
  }
49
57
  },
@@ -58,7 +66,11 @@ process.on('message', async (message) => {
58
66
  catch (e) {
59
67
  return {
60
68
  type: 'createDependenciesResult',
61
- payload: { success: false, error: e.stack, tx },
69
+ payload: {
70
+ success: false,
71
+ error: (0, serializable_error_1.createSerializableError)(e),
72
+ tx,
73
+ },
62
74
  };
63
75
  }
64
76
  },
@@ -73,7 +85,11 @@ process.on('message', async (message) => {
73
85
  catch (e) {
74
86
  return {
75
87
  type: 'processProjectGraphResult',
76
- payload: { success: false, error: e.stack, tx },
88
+ payload: {
89
+ success: false,
90
+ error: (0, serializable_error_1.createSerializableError)(e),
91
+ tx,
92
+ },
77
93
  };
78
94
  }
79
95
  },