nx 18.3.1 → 18.3.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.
Files changed (47) hide show
  1. package/.eslintrc.json +4 -0
  2. package/bin/nx.js +7 -19
  3. package/migrations.json +2 -1
  4. package/package.json +12 -12
  5. package/src/command-line/add/add.js +3 -1
  6. package/src/command-line/add/command-object.d.ts +1 -0
  7. package/src/command-line/add/command-object.js +6 -1
  8. package/src/command-line/graph/command-object.js +1 -1
  9. package/src/command-line/init/implementation/react/check-for-uncommitted-changes.js +6 -3
  10. package/src/command-line/show/command-object.js +1 -5
  11. package/src/command-line/yargs-utils/shared-options.d.ts +3 -0
  12. package/src/command-line/yargs-utils/shared-options.js +15 -6
  13. package/src/daemon/cache.js +18 -0
  14. package/src/daemon/client/client.js +3 -4
  15. package/src/daemon/server/handle-hash-tasks.js +2 -2
  16. package/src/daemon/server/project-graph-incremental-recomputation.js +1 -2
  17. package/src/daemon/server/server.js +1 -4
  18. package/src/daemon/socket-utils.js +2 -14
  19. package/src/executors/run-commands/run-commands.impl.js +62 -11
  20. package/src/native/index.d.ts +1 -4
  21. package/src/native/index.js +67 -259
  22. package/src/native/native-bindings.js +268 -0
  23. package/src/native/transform-objects.js +1 -0
  24. package/src/project-graph/error-types.d.ts +31 -1
  25. package/src/project-graph/error-types.js +62 -1
  26. package/src/project-graph/plugins/isolation/index.js +8 -4
  27. package/src/project-graph/plugins/isolation/messaging.d.ts +9 -6
  28. package/src/project-graph/plugins/isolation/messaging.js +27 -10
  29. package/src/project-graph/plugins/isolation/plugin-pool.d.ts +1 -1
  30. package/src/project-graph/plugins/isolation/plugin-pool.js +15 -24
  31. package/src/project-graph/plugins/isolation/plugin-worker.js +21 -5
  32. package/src/project-graph/plugins/loader.js +22 -18
  33. package/src/project-graph/project-graph.d.ts +2 -24
  34. package/src/project-graph/project-graph.js +11 -52
  35. package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
  36. package/src/tasks-runner/init-tasks-runner.js +2 -0
  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/tasks-runner/task-orchestrator.js +47 -29
  41. package/src/utils/dotenv.d.ts +7 -0
  42. package/src/utils/dotenv.js +22 -0
  43. package/src/utils/params.js +20 -17
  44. package/src/utils/serializable-error.d.ts +4 -0
  45. package/src/utils/serializable-error.js +28 -0
  46. package/src/daemon/daemon-project-graph-error.d.ts +0 -8
  47. package/src/daemon/daemon-project-graph-error.js +0 -13
package/.eslintrc.json CHANGED
@@ -25,6 +25,10 @@
25
25
  {
26
26
  "group": ["nx/*"],
27
27
  "message": "Circular import in 'nx' found. Use relative path."
28
+ },
29
+ {
30
+ "group": ["**/native-bindings", "**/native-bindings.js"],
31
+ "message": "Direct imports from native-bindings.js are not allowed. Import from index.js instead."
28
32
  }
29
33
  ]
30
34
  }
package/bin/nx.js CHANGED
@@ -3,8 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const find_workspace_root_1 = require("../src/utils/find-workspace-root");
5
5
  const chalk = require("chalk");
6
- const dotenv_1 = require("dotenv");
7
- const dotenv_expand_1 = require("dotenv-expand");
6
+ const dotenv_1 = require("../src/utils/dotenv");
8
7
  const init_local_1 = require("./init-local");
9
8
  const output_1 = require("../src/utils/output");
10
9
  const installation_directory_1 = require("../src/utils/installation-directory");
@@ -20,15 +19,18 @@ const client_1 = require("../src/daemon/client/client");
20
19
  function main() {
21
20
  if (process.argv[2] !== 'report' &&
22
21
  process.argv[2] !== '--version' &&
23
- process.argv[2] !== '--help') {
22
+ process.argv[2] !== '--help' &&
23
+ process.argv[2] !== 'reset') {
24
24
  (0, assert_supported_platform_1.assertSupportedPlatform)();
25
25
  }
26
26
  require('nx/src/utils/perf-logging');
27
+ const workspace = (0, find_workspace_root_1.findWorkspaceRoot)(process.cwd());
27
28
  perf_hooks_1.performance.mark('loading dotenv files:start');
28
- loadDotEnvFiles();
29
+ if (workspace) {
30
+ (0, dotenv_1.loadRootEnvFiles)(workspace.dir);
31
+ }
29
32
  perf_hooks_1.performance.mark('loading dotenv files:end');
30
33
  perf_hooks_1.performance.measure('loading dotenv files', 'loading dotenv files:start', 'loading dotenv files:end');
31
- const workspace = (0, find_workspace_root_1.findWorkspaceRoot)(process.cwd());
32
34
  // new is a special case because there is no local workspace to load
33
35
  if (process.argv[2] === 'new' ||
34
36
  process.argv[2] === '_migrate' ||
@@ -81,20 +83,6 @@ function main() {
81
83
  }
82
84
  }
83
85
  }
84
- /**
85
- * This loads dotenv files from:
86
- * - .env
87
- * - .local.env
88
- * - .env.local
89
- */
90
- function loadDotEnvFiles() {
91
- for (const file of ['.local.env', '.env.local', '.env']) {
92
- const myEnv = (0, dotenv_1.config)({
93
- path: file,
94
- });
95
- (0, dotenv_expand_1.expand)(myEnv);
96
- }
97
- }
98
86
  function handleNoWorkspace(globalNxVersion) {
99
87
  output_1.output.log({
100
88
  title: `The current directory isn't part of an Nx workspace.`,
package/migrations.json CHANGED
@@ -58,7 +58,8 @@
58
58
  "cli": "nx",
59
59
  "version": "16.8.0-beta.3",
60
60
  "description": "Escape $ in env variables",
61
- "implementation": "./src/migrations/update-16-8-0/escape-dollar-sign-env-variables"
61
+ "implementation": "./src/migrations/update-16-8-0/escape-dollar-sign-env-variables",
62
+ "x-repair-skip": true
62
63
  },
63
64
  "17.0.0-move-cache-directory": {
64
65
  "cli": "nx",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "18.3.1",
3
+ "version": "18.3.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": {
@@ -66,7 +66,7 @@
66
66
  "yargs-parser": "21.1.1",
67
67
  "node-machine-id": "1.1.12",
68
68
  "ora": "5.3.0",
69
- "@nrwl/tao": "18.3.1"
69
+ "@nrwl/tao": "18.3.3"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@swc-node/register": "^1.8.0",
@@ -81,16 +81,16 @@
81
81
  }
82
82
  },
83
83
  "optionalDependencies": {
84
- "@nx/nx-darwin-x64": "18.3.1",
85
- "@nx/nx-darwin-arm64": "18.3.1",
86
- "@nx/nx-linux-x64-gnu": "18.3.1",
87
- "@nx/nx-linux-x64-musl": "18.3.1",
88
- "@nx/nx-win32-x64-msvc": "18.3.1",
89
- "@nx/nx-linux-arm64-gnu": "18.3.1",
90
- "@nx/nx-linux-arm64-musl": "18.3.1",
91
- "@nx/nx-linux-arm-gnueabihf": "18.3.1",
92
- "@nx/nx-win32-arm64-msvc": "18.3.1",
93
- "@nx/nx-freebsd-x64": "18.3.1"
84
+ "@nx/nx-darwin-x64": "18.3.3",
85
+ "@nx/nx-darwin-arm64": "18.3.3",
86
+ "@nx/nx-linux-x64-gnu": "18.3.3",
87
+ "@nx/nx-linux-x64-musl": "18.3.3",
88
+ "@nx/nx-win32-x64-msvc": "18.3.3",
89
+ "@nx/nx-linux-arm64-gnu": "18.3.3",
90
+ "@nx/nx-linux-arm64-musl": "18.3.3",
91
+ "@nx/nx-linux-arm-gnueabihf": "18.3.3",
92
+ "@nx/nx-win32-arm64-msvc": "18.3.3",
93
+ "@nx/nx-freebsd-x64": "18.3.3"
94
94
  },
95
95
  "nx-migrations": {
96
96
  "migrations": "./migrations.json",
@@ -101,7 +101,9 @@ async function initializePlugin(pkgName, options) {
101
101
  process.env.NX_ADD_PLUGINS !== 'false' &&
102
102
  coreNxPlugins.includes(pkgName);
103
103
  }
104
- await (0, child_process_2.runNxAsync)(`g ${pkgName}:${initGenerator} --keepExistingVersions${updatePackageScripts ? ' --updatePackageScripts' : ''}`, {
104
+ await (0, child_process_2.runNxAsync)(`g ${pkgName}:${initGenerator} --keepExistingVersions${updatePackageScripts ? ' --updatePackageScripts' : ''}${options.__overrides_unparsed__.length
105
+ ? ' ' + options.__overrides_unparsed__.join(' ')
106
+ : ''}`, {
105
107
  silent: !options.verbose,
106
108
  });
107
109
  }
@@ -3,5 +3,6 @@ export interface AddOptions {
3
3
  packageSpecifier: string;
4
4
  updatePackageScripts?: boolean;
5
5
  verbose?: boolean;
6
+ __overrides_unparsed__: string[];
6
7
  }
7
8
  export declare const yargsAddCommand: CommandModule<Record<string, unknown>, AddOptions>;
@@ -1,10 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.yargsAddCommand = void 0;
4
+ const shared_options_1 = require("../yargs-utils/shared-options");
4
5
  exports.yargsAddCommand = {
5
6
  command: 'add <packageSpecifier>',
6
7
  describe: 'Install a plugin and initialize it.',
7
8
  builder: (yargs) => yargs
9
+ .parserConfiguration({
10
+ 'strip-dashed': true,
11
+ 'unknown-options-as-args': true,
12
+ })
8
13
  .positional('packageSpecifier', {
9
14
  type: 'string',
10
15
  description: 'The package name and optional version (e.g. `@nx/react` or `@nx/react@latest`) to install and initialize. If the version is not specified it will install the same version as the `nx` package for Nx core plugins or the latest version for other packages',
@@ -20,5 +25,5 @@ exports.yargsAddCommand = {
20
25
  .example('$0 add @nx/react', 'Install the latest version of the `@nx/react` package and run its `@nx/react:init` generator')
21
26
  .example('$0 add non-core-nx-plugin', 'Install the latest version of the `non-core-nx-plugin` package and run its `non-core-nx-plugin:init` generator if available')
22
27
  .example('$0 add @nx/react@17.0.0', 'Install version `17.0.0` of the `@nx/react` package and run its `@nx/react:init` generator'),
23
- handler: (args) => Promise.resolve().then(() => require('./add')).then((m) => m.addHandler(args)),
28
+ handler: (args) => Promise.resolve().then(() => require('./add')).then((m) => m.addHandler((0, shared_options_1.withOverrides)(args))),
24
29
  };
@@ -7,7 +7,7 @@ exports.yargsDepGraphCommand = {
7
7
  command: 'graph',
8
8
  describe: 'Graph dependencies within workspace',
9
9
  aliases: ['dep-graph'],
10
- builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)((0, shared_options_1.withAffectedOptions)((0, shared_options_1.withDepGraphOptions)(yargs)), 'dep-graph')
10
+ builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)((0, shared_options_1.withVerbose)((0, shared_options_1.withAffectedOptions)((0, shared_options_1.withDepGraphOptions)(yargs))), 'dep-graph')
11
11
  .option('affected', {
12
12
  type: 'boolean',
13
13
  description: 'Highlight affected projects',
@@ -3,12 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkForUncommittedChanges = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  function checkForUncommittedChanges() {
6
- const gitResult = (0, child_process_1.execSync)(`git status --porcelain`);
7
- if (gitResult.length > 0) {
6
+ const gitResult = (0, child_process_1.execSync)('git status --porcelain').toString();
7
+ const filteredResults = gitResult
8
+ .split('\n')
9
+ .filter((line) => !line.includes('.nx') && line.trim().length > 0);
10
+ if (filteredResults.length > 0) {
8
11
  console.log('❗️ Careful!');
9
12
  console.log('You have uncommitted changes in your repository.');
10
13
  console.log('');
11
- console.log(gitResult.toString());
14
+ console.log(filteredResults.join('\n').toString());
12
15
  console.log('Please commit your changes before running the migrator!');
13
16
  process.exit(1);
14
17
  }
@@ -26,7 +26,7 @@ exports.yargsShowCommand = {
26
26
  const showProjectsCommand = {
27
27
  command: 'projects',
28
28
  describe: 'Show a list of projects in the workspace',
29
- builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs)
29
+ builder: (yargs) => (0, shared_options_1.withVerbose)((0, shared_options_1.withAffectedOptions)(yargs))
30
30
  .option('affected', {
31
31
  type: 'boolean',
32
32
  description: 'Show only affected projects',
@@ -47,10 +47,6 @@ const showProjectsCommand = {
47
47
  type: 'string',
48
48
  description: 'Select only projects of the given type',
49
49
  choices: ['app', 'lib', 'e2e'],
50
- })
51
- .option('verbose', {
52
- type: 'boolean',
53
- description: 'Prints additional information about the commands (e.g., stack traces)',
54
50
  })
55
51
  .implies('untracked', 'affected')
56
52
  .implies('uncommitted', 'affected')
@@ -28,6 +28,9 @@ export declare function withTargetAndConfigurationOption(yargs: Argv, demandOpti
28
28
  export declare function withConfiguration(yargs: Argv): Argv<{
29
29
  configuration: string;
30
30
  }>;
31
+ export declare function withVerbose(yargs: Argv): Argv<{
32
+ verbose: boolean;
33
+ }>;
31
34
  export declare function withBatch(yargs: Argv): any;
32
35
  export declare function withAffectedOptions(yargs: Argv): Argv<ExcludeOptions & {
33
36
  files: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseCSV = exports.withRunOneOptions = exports.withDepGraphOptions = exports.withOutputStyleOption = exports.withOverrides = exports.withRunManyOptions = exports.withAffectedOptions = exports.withBatch = exports.withConfiguration = exports.withTargetAndConfigurationOption = exports.withRunOptions = exports.withExcludeOption = void 0;
3
+ exports.parseCSV = exports.withRunOneOptions = exports.withDepGraphOptions = exports.withOutputStyleOption = exports.withOverrides = exports.withRunManyOptions = exports.withAffectedOptions = exports.withBatch = exports.withVerbose = exports.withConfiguration = exports.withTargetAndConfigurationOption = exports.withRunOptions = exports.withExcludeOption = void 0;
4
4
  function withExcludeOption(yargs) {
5
5
  return yargs.option('exclude', {
6
6
  describe: 'Exclude certain projects from being processed',
@@ -10,7 +10,7 @@ function withExcludeOption(yargs) {
10
10
  }
11
11
  exports.withExcludeOption = withExcludeOption;
12
12
  function withRunOptions(yargs) {
13
- return withExcludeOption(yargs)
13
+ return withVerbose(withExcludeOption(yargs))
14
14
  .option('parallel', {
15
15
  describe: 'Max number of parallel processes [default is 3]',
16
16
  type: 'string',
@@ -41,10 +41,6 @@ function withRunOptions(yargs) {
41
41
  : value === 'false' || value === false
42
42
  ? false
43
43
  : value,
44
- })
45
- .option('verbose', {
46
- type: 'boolean',
47
- describe: 'Prints additional information about the commands (e.g., stack traces)',
48
44
  })
49
45
  .option('nxBail', {
50
46
  describe: 'Stop command execution after the first failed task',
@@ -96,6 +92,19 @@ function withConfiguration(yargs) {
96
92
  });
97
93
  }
98
94
  exports.withConfiguration = withConfiguration;
95
+ function withVerbose(yargs) {
96
+ return yargs
97
+ .option('verbose', {
98
+ describe: 'Prints additional information about the commands (e.g., stack traces)',
99
+ type: 'boolean',
100
+ })
101
+ .middleware((args) => {
102
+ if (args.verbose) {
103
+ process.env.NX_VERBOSE_LOGGING = 'true';
104
+ }
105
+ });
106
+ }
107
+ exports.withVerbose = withVerbose;
99
108
  function withBatch(yargs) {
100
109
  return yargs.options('batch', {
101
110
  type: 'boolean',
@@ -30,6 +30,24 @@ async function safelyCleanUpExistingProcess() {
30
30
  if (daemonProcessJson && daemonProcessJson.processId) {
31
31
  try {
32
32
  process.kill(daemonProcessJson.processId);
33
+ // we wait for the process to actually shut down before returning
34
+ await new Promise((resolve, reject) => {
35
+ let count = 0;
36
+ const interval = setInterval(() => {
37
+ try {
38
+ // sending a signal 0 to a process checks if the process is running instead of actually killing it
39
+ process.kill(daemonProcessJson.processId, 0);
40
+ }
41
+ catch (e) {
42
+ clearInterval(interval);
43
+ resolve();
44
+ }
45
+ if ((count += 1) > 200) {
46
+ clearInterval(interval);
47
+ reject(`Daemon process ${daemonProcessJson.processId} didn't exit after 2 seconds.`);
48
+ }
49
+ }, 10);
50
+ });
33
51
  }
34
52
  catch { }
35
53
  }
@@ -18,8 +18,7 @@ const promised_based_queue_1 = require("../../utils/promised-based-queue");
18
18
  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
- const daemon_project_graph_error_1 = require("../daemon-project-graph-error");
22
- const project_graph_1 = require("../../project-graph/project-graph");
21
+ const error_types_1 = require("../../project-graph/error-types");
23
22
  const DAEMON_ENV_SETTINGS = {
24
23
  NX_PROJECT_GLOB_CACHE: 'false',
25
24
  NX_CACHE_PROJECTS_CONFIG: 'false',
@@ -101,8 +100,8 @@ class DaemonClient {
101
100
  };
102
101
  }
103
102
  catch (e) {
104
- if (e.name === daemon_project_graph_error_1.DaemonProjectGraphError.name) {
105
- throw project_graph_1.ProjectGraphError.fromDaemonProjectGraphError(e);
103
+ if (e.name === error_types_1.DaemonProjectGraphError.name) {
104
+ throw error_types_1.ProjectGraphError.fromDaemonProjectGraphError(e);
106
105
  }
107
106
  else {
108
107
  throw e;
@@ -4,7 +4,7 @@ exports.handleHashTasks = void 0;
4
4
  const project_graph_incremental_recomputation_1 = require("./project-graph-incremental-recomputation");
5
5
  const task_hasher_1 = require("../../hasher/task-hasher");
6
6
  const configuration_1 = require("../../config/configuration");
7
- const daemon_project_graph_error_1 = require("../daemon-project-graph-error");
7
+ const error_types_1 = require("../../project-graph/error-types");
8
8
  /**
9
9
  * We use this not to recreated hasher for every hash operation
10
10
  * TaskHasher has a cache inside, so keeping it around results in faster performance
@@ -15,7 +15,7 @@ async function handleHashTasks(payload) {
15
15
  const { error, projectGraph: _graph, allWorkspaceFiles, fileMap, rustReferences, } = await (0, project_graph_incremental_recomputation_1.getCachedSerializedProjectGraphPromise)();
16
16
  let projectGraph = _graph;
17
17
  if (error) {
18
- if (error instanceof daemon_project_graph_error_1.DaemonProjectGraphError) {
18
+ if (error instanceof error_types_1.DaemonProjectGraphError) {
19
19
  projectGraph = error.projectGraph;
20
20
  }
21
21
  else {
@@ -13,7 +13,6 @@ const workspace_context_1 = require("../../utils/workspace-context");
13
13
  const workspace_root_1 = require("../../utils/workspace-root");
14
14
  const file_watcher_sockets_1 = require("./file-watching/file-watcher-sockets");
15
15
  const logger_1 = require("./logger");
16
- const daemon_project_graph_error_1 = require("../daemon-project-graph-error");
17
16
  const plugins_1 = require("./plugins");
18
17
  const error_types_1 = require("../../project-graph/error-types");
19
18
  let cachedSerializedProjectGraphPromise;
@@ -180,7 +179,7 @@ async function processFilesAndCreateAndSerializeProjectGraph(plugins) {
180
179
  }
181
180
  if (errors.length > 0) {
182
181
  return {
183
- error: new daemon_project_graph_error_1.DaemonProjectGraphError(errors, g.projectGraph, graphNodes.sourceMaps),
182
+ error: new error_types_1.DaemonProjectGraphError(errors, g.projectGraph, graphNodes.sourceMaps),
184
183
  projectGraph: null,
185
184
  projectFileMapCache: null,
186
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 daemon_project_graph_error_1 = require("./daemon-project-graph-error");
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 daemon_project_graph_error_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;
@@ -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 });
@@ -38,6 +41,7 @@ const propKeys = [
38
41
  'verbose',
39
42
  ];
40
43
  async function default_1(options, context) {
44
+ registerProcessListener();
41
45
  await loadEnvVars(options.envFile);
42
46
  const normalized = normalizeOptions(options);
43
47
  if (options.readyWhen && !options.parallel) {
@@ -136,9 +140,7 @@ function normalizeOptions(options) {
136
140
  return options;
137
141
  }
138
142
  async function runSerially(options, context) {
139
- const pseudoTerminal = pseudo_terminal_1.PseudoTerminal.isSupported()
140
- ? (0, pseudo_terminal_1.getPseudoTerminal)()
141
- : null;
143
+ pseudoTerminal ??= pseudo_terminal_1.PseudoTerminal.isSupported() ? (0, pseudo_terminal_1.getPseudoTerminal)() : null;
142
144
  let terminalOutput = '';
143
145
  for (const c of options.commands) {
144
146
  const result = await createProcess(pseudoTerminal, c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
@@ -172,6 +174,7 @@ async function createProcess(pseudoTerminal, commandConfig, readyWhen, color, cw
172
174
  jsEnv: env,
173
175
  quiet: !streamOutput,
174
176
  });
177
+ childProcesses.add(cp);
175
178
  return new Promise((res) => {
176
179
  cp.onOutput((output) => {
177
180
  terminalOutput += output;
@@ -202,14 +205,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
202
205
  env,
203
206
  cwd,
204
207
  });
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);
208
+ childProcesses.add(childProcess);
213
209
  childProcess.stdout.on('data', (data) => {
214
210
  const output = addColorAndPrefix(data, commandConfig);
215
211
  terminalOutput += output;
@@ -239,6 +235,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
239
235
  res({ success: false, terminalOutput });
240
236
  });
241
237
  childProcess.on('exit', (code) => {
238
+ childProcesses.delete(childProcess);
242
239
  if (!readyWhen) {
243
240
  res({ success: code === 0, terminalOutput });
244
241
  }
@@ -361,3 +358,57 @@ function filterPropKeysFromUnParsedOptions(__unparsed__, unparsedCommandArgs = {
361
358
  }
362
359
  return parsedOptions;
363
360
  }
361
+ let registered = false;
362
+ function registerProcessListener() {
363
+ if (registered) {
364
+ return;
365
+ }
366
+ registered = true;
367
+ // When the nx process gets a message, it will be sent into the task's process
368
+ process.on('message', (message) => {
369
+ // this.publisher.publish(message.toString());
370
+ if (pseudoTerminal) {
371
+ pseudoTerminal.sendMessageToChildren(message);
372
+ }
373
+ childProcesses.forEach((p) => {
374
+ if ('connected' in p && p.connected) {
375
+ p.send(message);
376
+ }
377
+ });
378
+ });
379
+ // Terminate any task processes on exit
380
+ process.on('exit', () => {
381
+ childProcesses.forEach((p) => {
382
+ if ('connected' in p ? p.connected : p.isAlive) {
383
+ p.kill();
384
+ }
385
+ });
386
+ });
387
+ process.on('SIGINT', () => {
388
+ childProcesses.forEach((p) => {
389
+ if ('connected' in p ? p.connected : p.isAlive) {
390
+ p.kill('SIGTERM');
391
+ }
392
+ });
393
+ // we exit here because we don't need to write anything to cache.
394
+ process.exit((0, exit_codes_1.signalToCode)('SIGINT'));
395
+ });
396
+ process.on('SIGTERM', () => {
397
+ childProcesses.forEach((p) => {
398
+ if ('connected' in p ? p.connected : p.isAlive) {
399
+ p.kill('SIGTERM');
400
+ }
401
+ });
402
+ // no exit here because we expect child processes to terminate which
403
+ // will store results to the cache and will terminate this process
404
+ });
405
+ process.on('SIGHUP', () => {
406
+ childProcesses.forEach((p) => {
407
+ if ('connected' in p ? p.connected : p.isAlive) {
408
+ p.kill('SIGTERM');
409
+ }
410
+ });
411
+ // no exit here because we expect child processes to terminate which
412
+ // will store results to the cache and will terminate this process
413
+ });
414
+ }
@@ -29,11 +29,8 @@ export function findImports(projectFileMap: Record<string, Array<string>>): Arra
29
29
  * This wont be needed once the project graph is created in Rust
30
30
  */
31
31
  export function transferProjectGraph(projectGraph: ProjectGraph): ExternalObject<ProjectGraph>
32
- export interface ExternalNodeData {
33
- version: string
34
- hash?: string
35
- }
36
32
  export interface ExternalNode {
33
+ packageName?: string
37
34
  version: string
38
35
  hash?: string
39
36
  }