nx 18.4.0-canary.20240418-e549ea2 → 19.0.0-beta.1

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.
@@ -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) {
@@ -214,37 +214,55 @@ class TaskOrchestrator {
214
214
  if (process.env.NX_RUN_COMMANDS_DIRECTLY !== 'false' &&
215
215
  targetConfiguration.executor === 'nx:run-commands' &&
216
216
  !shouldPrefix) {
217
- const { schema } = (0, utils_1.getExecutorForTask)(task, this.projectGraph);
218
- const isRunOne = this.initiatingProject != null;
219
- const combinedOptions = (0, params_1.combineOptionsForExecutor)(task.overrides, task.target.configuration ?? targetConfiguration.defaultConfiguration, targetConfiguration, schema, task.target.project, (0, path_1.relative)(task.projectRoot ?? workspace_root_1.workspaceRoot, process.cwd()), process.env.NX_VERBOSE_LOGGING === 'true');
220
- if (combinedOptions.env) {
221
- env = {
222
- ...env,
223
- ...combinedOptions.env,
224
- };
225
- }
226
- if (streamOutput) {
227
- const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
228
- output_1.output.logCommand(args.join(' '));
217
+ try {
218
+ const { schema } = (0, utils_1.getExecutorForTask)(task, this.projectGraph);
219
+ const isRunOne = this.initiatingProject != null;
220
+ const combinedOptions = (0, params_1.combineOptionsForExecutor)(task.overrides, task.target.configuration ??
221
+ targetConfiguration.defaultConfiguration, targetConfiguration, schema, task.target.project, (0, path_1.relative)(task.projectRoot ?? workspace_root_1.workspaceRoot, process.cwd()), process.env.NX_VERBOSE_LOGGING === 'true');
222
+ if (combinedOptions.env) {
223
+ env = {
224
+ ...env,
225
+ ...combinedOptions.env,
226
+ };
227
+ }
228
+ if (streamOutput) {
229
+ const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
230
+ output_1.output.logCommand(args.join(' '));
231
+ }
232
+ const { success, terminalOutput } = await (0, run_commands_impl_1.default)({
233
+ ...combinedOptions,
234
+ env,
235
+ usePty: isRunOne && !this.tasksSchedule.hasTasks(),
236
+ streamOutput,
237
+ }, {
238
+ root: workspace_root_1.workspaceRoot, // only root is needed in runCommandsImpl
239
+ });
240
+ const status = success ? 'success' : 'failure';
241
+ if (!streamOutput) {
242
+ this.options.lifeCycle.printTaskTerminalOutput(task, status, terminalOutput);
243
+ }
244
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
245
+ results.push({
246
+ task,
247
+ status,
248
+ terminalOutput,
249
+ });
229
250
  }
230
- const { success, terminalOutput } = await (0, run_commands_impl_1.default)({
231
- ...combinedOptions,
232
- env,
233
- usePty: isRunOne && !this.tasksSchedule.hasTasks(),
234
- streamOutput,
235
- }, {
236
- root: workspace_root_1.workspaceRoot, // only root is needed in runCommandsImpl
237
- });
238
- const status = success ? 'success' : 'failure';
239
- if (!streamOutput) {
240
- this.options.lifeCycle.printTaskTerminalOutput(task, status, terminalOutput);
251
+ catch (e) {
252
+ if (process.env.NX_VERBOSE_LOGGING === 'true') {
253
+ console.error(e);
254
+ }
255
+ else {
256
+ console.error(e.message);
257
+ }
258
+ const terminalOutput = e.stack ?? e.message ?? '';
259
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
260
+ results.push({
261
+ task,
262
+ status: 'failure',
263
+ terminalOutput,
264
+ });
241
265
  }
242
- (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
243
- results.push({
244
- task,
245
- status,
246
- terminalOutput,
247
- });
248
266
  }
249
267
  else {
250
268
  // cache prep
@@ -176,26 +176,29 @@ function validateObject(opts, schema, definitions) {
176
176
  }
177
177
  }
178
178
  if (schema.oneOf) {
179
- for (const s of schema.oneOf) {
180
- const errors = [];
181
- for (const s of schema.oneOf) {
182
- try {
183
- validateObject(opts, s, definitions);
184
- }
185
- catch (e) {
186
- errors.push(e);
187
- }
188
- }
189
- if (errors.length === schema.oneOf.length) {
190
- throw new Error(`Options did not match schema. Please fix 1 of the following errors:\n${errors
191
- .map((e) => ' - ' + e.message)
192
- .join('\n')}`);
179
+ const matches = [];
180
+ const errors = [];
181
+ for (const propertyDescription of schema.oneOf) {
182
+ try {
183
+ validateObject(opts, propertyDescription, definitions);
184
+ matches.push(propertyDescription);
193
185
  }
194
- if (errors.length < schema.oneOf.length - 1) {
195
- // TODO: This error could be better.
196
- throw new Error(`Options did not match schema.`);
186
+ catch (error) {
187
+ errors.push(error);
197
188
  }
198
189
  }
190
+ // If the options matched none of the oneOf property descriptions
191
+ if (matches.length === 0) {
192
+ throw new Error(`Options did not match schema: ${JSON.stringify(opts, null, 2)}.\nPlease fix 1 of the following errors:\n${errors
193
+ .map((e) => ' - ' + e.message)
194
+ .join('\n')}`);
195
+ }
196
+ // If the options matched none of the oneOf property descriptions
197
+ if (matches.length > 1) {
198
+ throw new Error(`Options did not match schema: ${JSON.stringify(opts, null, 2)}.\nShould only match one of \n${matches
199
+ .map((m) => ' - ' + JSON.stringify(m))
200
+ .join('\n')}`);
201
+ }
199
202
  }
200
203
  (schema.required ?? []).forEach((p) => {
201
204
  if (opts[p] === undefined) {
@@ -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;