nx 19.0.0-beta.0 → 19.0.0-beta.2

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.
@@ -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;
@@ -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
+ }
@@ -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;
@@ -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
  },
@@ -14,10 +14,11 @@ const find_project_for_path_1 = require("../utils/find-project-for-path");
14
14
  const path_1 = require("../../utils/path");
15
15
  const logger_1 = require("../../utils/logger");
16
16
  const node_path_1 = require("node:path");
17
- const path = require("node:path/posix");
18
17
  const retrieve_workspace_files_1 = require("../utils/retrieve-workspace-files");
19
18
  const utils_1 = require("./utils");
20
19
  const internal_api_1 = require("./internal-api");
20
+ const error_types_1 = require("../error-types");
21
+ const path = require("node:path/posix");
21
22
  function readPluginPackageJson(pluginName, projects, paths = (0, installation_directory_1.getNxRequirePaths)()) {
22
23
  try {
23
24
  const result = (0, package_json_1.readModulePackageJsonWithoutFallbacks)(pluginName, paths);
@@ -174,26 +175,29 @@ function loadNxPlugin(plugin, root) {
174
175
  }
175
176
  exports.loadNxPlugin = loadNxPlugin;
176
177
  async function loadNxPluginAsync(pluginConfiguration, paths, root) {
177
- try {
178
- require.resolve(typeof pluginConfiguration === 'string'
179
- ? pluginConfiguration
180
- : pluginConfiguration.plugin);
181
- }
182
- catch {
183
- // If a plugin cannot be resolved, we will need projects to resolve it
184
- projectsWithoutInference ??=
185
- await (0, retrieve_workspace_files_1.retrieveProjectConfigurationsWithoutPluginInference)(root);
186
- }
187
178
  const moduleName = typeof pluginConfiguration === 'string'
188
179
  ? pluginConfiguration
189
180
  : pluginConfiguration.plugin;
190
- performance.mark(`Load Nx Plugin: ${moduleName} - start`);
191
- let { pluginPath, name } = await getPluginPathAndName(moduleName, paths, projectsWithoutInference, root);
192
- const plugin = (0, utils_1.normalizeNxPlugin)(await importPluginModule(pluginPath));
193
- plugin.name ??= name;
194
- performance.mark(`Load Nx Plugin: ${moduleName} - end`);
195
- performance.measure(`Load Nx Plugin: ${moduleName}`, `Load Nx Plugin: ${moduleName} - start`, `Load Nx Plugin: ${moduleName} - end`);
196
- return new internal_api_1.LoadedNxPlugin(plugin, pluginConfiguration);
181
+ try {
182
+ try {
183
+ require.resolve(moduleName);
184
+ }
185
+ catch {
186
+ // If a plugin cannot be resolved, we will need projects to resolve it
187
+ projectsWithoutInference ??=
188
+ await (0, retrieve_workspace_files_1.retrieveProjectConfigurationsWithoutPluginInference)(root);
189
+ }
190
+ performance.mark(`Load Nx Plugin: ${moduleName} - start`);
191
+ let { pluginPath, name } = await getPluginPathAndName(moduleName, paths, projectsWithoutInference, root);
192
+ const plugin = (0, utils_1.normalizeNxPlugin)(await importPluginModule(pluginPath));
193
+ plugin.name ??= name;
194
+ performance.mark(`Load Nx Plugin: ${moduleName} - end`);
195
+ performance.measure(`Load Nx Plugin: ${moduleName}`, `Load Nx Plugin: ${moduleName} - start`, `Load Nx Plugin: ${moduleName} - end`);
196
+ return new internal_api_1.LoadedNxPlugin(plugin, pluginConfiguration);
197
+ }
198
+ catch (e) {
199
+ throw new error_types_1.LoadPluginError(moduleName, e);
200
+ }
197
201
  }
198
202
  exports.loadNxPluginAsync = loadNxPluginAsync;
199
203
  async function importPluginModule(pluginPath) {
@@ -388,7 +388,7 @@ function mergeTargetConfigurations(target, baseTarget, projectConfigSourceMap, s
388
388
  const { configurations: defaultConfigurations, options: defaultOptions, ...baseTargetProperties } = baseTarget ?? {};
389
389
  // Target is "compatible", e.g. executor is defined only once or is the same
390
390
  // in both places. This means that it is likely safe to merge
391
- const isCompatible = isCompatibleTarget(baseTargetProperties, target);
391
+ const isCompatible = isCompatibleTarget(baseTarget ?? {}, target);
392
392
  // If the targets are not compatible, we would normally overwrite the old target
393
393
  // with the new one. However, we have a special case for targets that have the
394
394
  // ONLY_MODIFIES_EXISTING_TARGET symbol set. This prevents the merged target
@@ -9,12 +9,12 @@ import { LoadedNxPlugin } from '../plugins/internal-api';
9
9
  * @param nxJson
10
10
  */
11
11
  export declare function retrieveWorkspaceFiles(workspaceRoot: string, projectRootMap: Record<string, string>): Promise<{
12
- allWorkspaceFiles: import("nx/src/devkit-exports").FileData[];
12
+ allWorkspaceFiles: import("../file-utils").FileData[];
13
13
  fileMap: {
14
14
  projectFileMap: ProjectFiles;
15
- nonProjectFiles: import("nx/src/native").FileData[];
15
+ nonProjectFiles: import("../../native").FileData[];
16
16
  };
17
- rustReferences: import("nx/src/native").NxWorkspaceFilesExternals;
17
+ rustReferences: import("../../native").NxWorkspaceFilesExternals;
18
18
  }>;
19
19
  /**
20
20
  * Walk through the workspace and return `ProjectConfigurations`. Only use this if the projectFileMap is not needed.
@@ -24,6 +24,10 @@ const EXTENDED_LEFT_PAD = ` `;
24
24
  */
25
25
  async function createRunManyDynamicOutputRenderer({ projectNames, tasks, args, overrides, }) {
26
26
  cliCursor.hide();
27
+ // Show the cursor again after the process exits
28
+ process.on('exit', () => {
29
+ cliCursor.show();
30
+ });
27
31
  let resolveRenderIsDonePromise;
28
32
  const renderIsDone = new Promise((resolve) => (resolveRenderIsDonePromise = resolve)).then(() => {
29
33
  clearRenderInterval();
@@ -24,6 +24,10 @@ const EXTENDED_LEFT_PAD = ` `;
24
24
  */
25
25
  async function createRunOneDynamicOutputRenderer({ initiatingProject, tasks, args, overrides, }) {
26
26
  cliCursor.hide();
27
+ // Show the cursor again after the process exits
28
+ process.on('exit', () => {
29
+ cliCursor.show();
30
+ });
27
31
  let resolveRenderIsDonePromise;
28
32
  const renderIsDone = new Promise((resolve) => (resolveRenderIsDonePromise = resolve)).then(() => {
29
33
  clearRenderInterval();
@@ -142,6 +142,12 @@ function supportedPtyPlatform() {
142
142
  if (process.platform !== 'win32') {
143
143
  return true;
144
144
  }
145
+ // TODO: Re-enable Windows support when it's stable
146
+ // Currently, there's an issue with control chars.
147
+ // See: https://github.com/nrwl/nx/issues/22358
148
+ if (process.env.NX_WINDOWS_PTY_SUPPORT !== 'true') {
149
+ return false;
150
+ }
145
151
  let windowsVersion = os.release().split('.');
146
152
  let windowsBuild = windowsVersion[2];
147
153
  if (!windowsBuild) {
@@ -0,0 +1,4 @@
1
+ /**
2
+ * This function transforms an error into an object which can be properly serialized and deserialized to be sent between processes.
3
+ */
4
+ export declare function createSerializableError<T extends Error>(error: T): T;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSerializableError = void 0;
4
+ /**
5
+ * This function transforms an error into an object which can be properly serialized and deserialized to be sent between processes.
6
+ */
7
+ function createSerializableError(error) {
8
+ const res = {};
9
+ Object.getOwnPropertyNames(error).forEach((k) => {
10
+ let value = error[k];
11
+ // If an error has an error as a property such as cause, it will be transformed into a serializable error
12
+ if (typeof value === 'object' && value instanceof Error) {
13
+ value = createSerializableError(value);
14
+ }
15
+ // If an error has an array of errors as a property, they will be transformed into serializable errors
16
+ if (Array.isArray(value)) {
17
+ value = value.map((v) => {
18
+ if (typeof v === 'object' && v instanceof Error) {
19
+ return createSerializableError(v);
20
+ }
21
+ return v;
22
+ });
23
+ }
24
+ res[k] = value;
25
+ });
26
+ return res;
27
+ }
28
+ exports.createSerializableError = createSerializableError;