nx 18.1.0-canary.20240227-452d845 → 18.1.0-canary.20240228-4d13753

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "18.1.0-canary.20240227-452d845",
3
+ "version": "18.1.0-canary.20240228-4d13753",
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.1.0-canary.20240227-452d845"
69
+ "@nrwl/tao": "18.1.0-canary.20240228-4d13753"
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.1.0-canary.20240227-452d845",
85
- "@nx/nx-darwin-arm64": "18.1.0-canary.20240227-452d845",
86
- "@nx/nx-linux-x64-gnu": "18.1.0-canary.20240227-452d845",
87
- "@nx/nx-linux-x64-musl": "18.1.0-canary.20240227-452d845",
88
- "@nx/nx-win32-x64-msvc": "18.1.0-canary.20240227-452d845",
89
- "@nx/nx-linux-arm64-gnu": "18.1.0-canary.20240227-452d845",
90
- "@nx/nx-linux-arm64-musl": "18.1.0-canary.20240227-452d845",
91
- "@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.20240227-452d845",
92
- "@nx/nx-win32-arm64-msvc": "18.1.0-canary.20240227-452d845",
93
- "@nx/nx-freebsd-x64": "18.1.0-canary.20240227-452d845"
84
+ "@nx/nx-darwin-x64": "18.1.0-canary.20240228-4d13753",
85
+ "@nx/nx-darwin-arm64": "18.1.0-canary.20240228-4d13753",
86
+ "@nx/nx-linux-x64-gnu": "18.1.0-canary.20240228-4d13753",
87
+ "@nx/nx-linux-x64-musl": "18.1.0-canary.20240228-4d13753",
88
+ "@nx/nx-win32-x64-msvc": "18.1.0-canary.20240228-4d13753",
89
+ "@nx/nx-linux-arm64-gnu": "18.1.0-canary.20240228-4d13753",
90
+ "@nx/nx-linux-arm64-musl": "18.1.0-canary.20240228-4d13753",
91
+ "@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.20240228-4d13753",
92
+ "@nx/nx-win32-arm64-msvc": "18.1.0-canary.20240228-4d13753",
93
+ "@nx/nx-freebsd-x64": "18.1.0-canary.20240228-4d13753"
94
94
  },
95
95
  "nx-migrations": {
96
96
  "migrations": "./migrations.json",
@@ -9,6 +9,7 @@ const nx_deps_cache_1 = require("./nx-deps-cache");
9
9
  const implicit_project_dependencies_1 = require("./utils/implicit-project-dependencies");
10
10
  const normalize_project_nodes_1 = require("./utils/normalize-project-nodes");
11
11
  const internal_api_1 = require("./plugins/internal-api");
12
+ const utils_1 = require("./plugins/utils");
12
13
  const typescript_1 = require("../plugins/js/utils/typescript");
13
14
  const fileutils_1 = require("../utils/fileutils");
14
15
  const project_graph_builder_1 = require("./project-graph-builder");
@@ -145,7 +146,7 @@ async function updateProjectGraphWithPlugins(context, initProjectGraph) {
145
146
  let graph = initProjectGraph;
146
147
  for (const plugin of plugins) {
147
148
  try {
148
- if ((0, internal_api_1.isNxPluginV1)(plugin) &&
149
+ if ((0, utils_1.isNxPluginV1)(plugin) &&
149
150
  plugin.processProjectGraph &&
150
151
  !plugin.createDependencies) {
151
152
  output_1.output.warn({
@@ -183,7 +184,7 @@ async function updateProjectGraphWithPlugins(context, initProjectGraph) {
183
184
  }
184
185
  }
185
186
  const builder = new project_graph_builder_1.ProjectGraphBuilder(graph, context.fileMap.projectFileMap, context.fileMap.nonProjectFiles);
186
- const createDependencyPlugins = plugins.filter((plugin) => (0, internal_api_1.isNxPluginV2)(plugin) && plugin.createDependencies);
187
+ const createDependencyPlugins = plugins.filter((plugin) => (0, utils_1.isNxPluginV2)(plugin) && plugin.createDependencies);
187
188
  await Promise.all(createDependencyPlugins.map(async (plugin) => {
188
189
  perf_hooks_1.performance.mark(`${plugin.name}:createDependencies - start`);
189
190
  // Set this globally to allow plugins to know if they are being called from the project graph creation
@@ -1,6 +1,6 @@
1
1
  import { PluginConfiguration } from '../../config/nx-json';
2
2
  import { NxPluginV1 } from '../../utils/nx-plugin.deprecated';
3
- import { CreateNodesContext, CreateNodesResult, NxPlugin, NxPluginV2 } from './public-api';
3
+ import { CreateNodesContext, CreateNodesResult, NxPluginV2 } from './public-api';
4
4
  export type CreateNodesResultWithContext = CreateNodesResult & {
5
5
  file: string;
6
6
  pluginName: string;
@@ -15,7 +15,4 @@ export type RemotePlugin = Omit<NormalizedPlugin, 'createNodes'> & {
15
15
  export declare const nxPluginCache: Map<unknown, RemotePlugin>;
16
16
  export declare function loadNxPlugins(plugins: PluginConfiguration[], root?: string): Promise<RemotePlugin[]>;
17
17
  export declare function loadNxPlugin(plugin: PluginConfiguration, root?: string): Promise<RemotePlugin>;
18
- export declare function isNxPluginV2(plugin: NxPlugin): plugin is NxPluginV2;
19
- export declare function isNxPluginV1(plugin: NxPlugin | RemotePlugin): plugin is NxPluginV1;
20
- export declare function normalizeNxPlugin(plugin: NxPlugin): NormalizedPlugin;
21
18
  export declare function getDefaultPlugins(root: string): Promise<string[]>;
@@ -2,10 +2,8 @@
2
2
  // This file contains the bits and bobs of the internal API for loading and interacting with Nx plugins.
3
3
  // For the public API, used by plugin authors, see `./public-api.ts`.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.getDefaultPlugins = exports.normalizeNxPlugin = exports.isNxPluginV1 = exports.isNxPluginV2 = exports.loadNxPlugin = exports.loadNxPlugins = exports.nxPluginCache = void 0;
5
+ exports.getDefaultPlugins = exports.loadNxPlugin = exports.loadNxPlugins = exports.nxPluginCache = void 0;
6
6
  const path_1 = require("path");
7
- const workspaces_1 = require("../../config/workspaces");
8
- const globs_1 = require("../../utils/globs");
9
7
  const workspace_root_1 = require("../../utils/workspace-root");
10
8
  const angular_json_1 = require("../../adapter/angular-json");
11
9
  const plugin_pool_1 = require("./plugin-pool");
@@ -36,40 +34,6 @@ async function loadNxPlugin(plugin, root = workspace_root_1.workspaceRoot) {
36
34
  return loadedPlugin;
37
35
  }
38
36
  exports.loadNxPlugin = loadNxPlugin;
39
- function isNxPluginV2(plugin) {
40
- return 'createNodes' in plugin || 'createDependencies' in plugin;
41
- }
42
- exports.isNxPluginV2 = isNxPluginV2;
43
- function isNxPluginV1(plugin) {
44
- return 'processProjectGraph' in plugin || 'projectFilePatterns' in plugin;
45
- }
46
- exports.isNxPluginV1 = isNxPluginV1;
47
- function normalizeNxPlugin(plugin) {
48
- if (isNxPluginV2(plugin)) {
49
- return plugin;
50
- }
51
- if (isNxPluginV1(plugin) && plugin.projectFilePatterns) {
52
- return {
53
- ...plugin,
54
- createNodes: [
55
- `*/**/${(0, globs_1.combineGlobPatterns)(plugin.projectFilePatterns)}`,
56
- (configFilePath) => {
57
- const root = (0, path_1.dirname)(configFilePath);
58
- return {
59
- projects: {
60
- [root]: {
61
- name: (0, workspaces_1.toProjectName)(configFilePath),
62
- targets: plugin.registerProjectTargets?.(configFilePath),
63
- },
64
- },
65
- };
66
- },
67
- ],
68
- };
69
- }
70
- return plugin;
71
- }
72
- exports.normalizeNxPlugin = normalizeNxPlugin;
73
37
  async function getDefaultPlugins(root) {
74
38
  return [
75
39
  (0, path_1.join)(__dirname, '../../plugins/js'),
@@ -22,15 +22,12 @@ export interface PluginWorkerLoadResult {
22
22
  error: string;
23
23
  };
24
24
  }
25
- export interface PluginWorkerShutdownMessage {
26
- type: 'shutdown';
27
- payload: undefined;
28
- }
29
25
  export interface PluginWorkerCreateNodesMessage {
30
26
  type: 'createNodes';
31
27
  payload: {
32
28
  configFiles: string[];
33
29
  context: CreateNodesContext;
30
+ tx: string;
34
31
  };
35
32
  }
36
33
  export interface PluginWorkerCreateNodesResult {
@@ -38,15 +35,18 @@ export interface PluginWorkerCreateNodesResult {
38
35
  payload: {
39
36
  success: true;
40
37
  result: Awaited<ReturnType<RemotePlugin['createNodes'][1]>>;
38
+ tx: string;
41
39
  } | {
42
40
  success: false;
43
41
  error: string;
42
+ tx: string;
44
43
  };
45
44
  }
46
45
  export interface PluginCreateDependenciesMessage {
47
46
  type: 'createDependencies';
48
47
  payload: {
49
48
  context: CreateDependenciesContext;
49
+ tx: string;
50
50
  };
51
51
  }
52
52
  export interface PluginCreateDependenciesResult {
@@ -54,9 +54,11 @@ export interface PluginCreateDependenciesResult {
54
54
  payload: {
55
55
  dependencies: ReturnType<RemotePlugin['createDependencies']>;
56
56
  success: true;
57
+ tx: string;
57
58
  } | {
58
59
  success: false;
59
60
  error: string;
61
+ tx: string;
60
62
  };
61
63
  }
62
64
  export interface PluginWorkerProcessProjectGraphMessage {
@@ -64,6 +66,7 @@ export interface PluginWorkerProcessProjectGraphMessage {
64
66
  payload: {
65
67
  graph: ProjectGraph;
66
68
  ctx: ProjectGraphProcessorContext;
69
+ tx: string;
67
70
  };
68
71
  }
69
72
  export interface PluginWorkerProcessProjectGraphResult {
@@ -71,12 +74,14 @@ export interface PluginWorkerProcessProjectGraphResult {
71
74
  payload: {
72
75
  graph: ProjectGraph;
73
76
  success: true;
77
+ tx: string;
74
78
  } | {
75
79
  success: false;
76
80
  error: string;
81
+ tx: string;
77
82
  };
78
83
  }
79
- export type PluginWorkerMessage = PluginWorkerLoadMessage | PluginWorkerShutdownMessage | PluginWorkerCreateNodesMessage | PluginCreateDependenciesMessage | PluginWorkerProcessProjectGraphMessage;
84
+ export type PluginWorkerMessage = PluginWorkerLoadMessage | PluginWorkerCreateNodesMessage | PluginCreateDependenciesMessage | PluginWorkerProcessProjectGraphMessage;
80
85
  export type PluginWorkerResult = PluginWorkerLoadResult | PluginWorkerCreateNodesResult | PluginCreateDependenciesResult | PluginWorkerProcessProjectGraphResult;
81
86
  type MaybePromise<T> = T | Promise<T>;
82
87
  type MessageHandlerReturn<T extends PluginWorkerMessage | PluginWorkerResult> = T extends PluginWorkerResult ? MaybePromise<PluginWorkerMessage | void> : MaybePromise<PluginWorkerResult | void>;
@@ -1,4 +1,4 @@
1
1
  import { PluginConfiguration } from '../../config/nx-json';
2
2
  import { RemotePlugin } from './internal-api';
3
3
  export declare function loadRemoteNxPlugin(plugin: PluginConfiguration, root: string): Promise<RemotePlugin>;
4
- export declare function shutdownPluginWorkers(): Promise<any[]>;
4
+ export declare function shutdownPluginWorkers(): Promise<void>;
@@ -3,11 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.shutdownPluginWorkers = exports.loadRemoteNxPlugin = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  const path = require("path");
6
- const logger_1 = require("../../utils/logger");
6
+ // TODO (@AgentEnder): After scoped verbose logging is implemented, re-add verbose logs here.
7
+ // import { logger } from '../../utils/logger';
7
8
  const internal_api_1 = require("./internal-api");
8
9
  const messaging_1 = require("./messaging");
9
- const pool = [];
10
+ const pool = new Set();
10
11
  const pidMap = new Map();
12
+ // transaction id (tx) -> Promise, Resolver, Rejecter
13
+ // Makes sure that we can resolve the correct promise when the worker sends back the result
14
+ const promiseBank = new Map();
11
15
  function loadRemoteNxPlugin(plugin, root) {
12
16
  // this should only really be true when running unit tests within
13
17
  // the Nx repo. We still need to start the worker in this case,
@@ -32,11 +36,11 @@ function loadRemoteNxPlugin(plugin, root) {
32
36
  ],
33
37
  });
34
38
  worker.send((0, messaging_1.createMessage)({ type: 'load', payload: { plugin, root } }));
35
- pool.push(worker);
36
- logger_1.logger.verbose(`[plugin-worker] started worker: ${worker.pid}`);
39
+ pool.add(worker);
40
+ // logger.verbose(`[plugin-worker] started worker: ${worker.pid}`);
37
41
  return new Promise((res, rej) => {
38
42
  worker.on('message', createWorkerHandler(worker, res, rej));
39
- worker.on('exit', () => workerOnExitHandler(worker));
43
+ worker.on('exit', createWorkerExitHandler(worker));
40
44
  });
41
45
  }
42
46
  exports.loadRemoteNxPlugin = loadRemoteNxPlugin;
@@ -46,22 +50,19 @@ async function shutdownPluginWorkers() {
46
50
  internal_api_1.nxPluginCache.clear();
47
51
  // Marks the workers as shutdown so that we don't report unexpected exits
48
52
  pluginWorkersShutdown = true;
49
- const promises = [];
53
+ // logger.verbose(`[plugin-pool] starting worker shutdown`);
54
+ const pending = getPendingPromises(pool, pidMap);
55
+ if (pending.length > 0) {
56
+ // logger.verbose(
57
+ // `[plugin-pool] waiting for ${pending.length} pending operations to complete`
58
+ // );
59
+ await Promise.all(pending);
60
+ }
61
+ // logger.verbose(`[plugin-pool] all pending operations completed`);
50
62
  for (const p of pool) {
51
- p.send((0, messaging_1.createMessage)({ type: 'shutdown', payload: undefined }), (error) => {
52
- if (error) {
53
- // This occurs when the worker is already dead, and we can ignore it
54
- }
55
- else {
56
- promises.push(
57
- // Create a promise that resolves when the worker exits
58
- new Promise((res, rej) => {
59
- p.once('exit', () => res());
60
- }));
61
- }
62
- });
63
+ p.kill('SIGINT');
63
64
  }
64
- return Promise.all(promises);
65
+ // logger.verbose(`[plugin-pool] all workers killed`);
65
66
  }
66
67
  exports.shutdownPluginWorkers = shutdownPluginWorkers;
67
68
  /**
@@ -72,67 +73,74 @@ exports.shutdownPluginWorkers = shutdownPluginWorkers;
72
73
  * @returns Function to handle messages from the worker
73
74
  */
74
75
  function createWorkerHandler(worker, onload, onloadError) {
75
- // We store resolver and rejecter functions in the outer scope so that we can
76
- // resolve/reject the promise from the message handler. The flow is something like:
77
- // 1. plugin api called
78
- // 2. remote plugin sends message to worker, creates promise and stores resolver/rejecter
79
- // 3. worker performs API request
80
- // 4. worker sends result back to main process
81
- // 5. main process resolves/rejects promise based on result
82
- let createNodesResolver;
83
- let createNodesRejecter;
84
- let createDependenciesResolver;
85
- let createDependenciesRejecter;
86
- let processProjectGraphResolver;
87
- let processProjectGraphRejecter;
88
76
  let pluginName;
89
77
  return function (message) {
90
78
  const parsed = JSON.parse(message);
91
- logger_1.logger.verbose(`[plugin-pool] received message: ${parsed.type} from ${pluginName ?? worker.pid}`);
79
+ // logger.verbose(
80
+ // `[plugin-pool] received message: ${parsed.type} from ${
81
+ // pluginName ?? worker.pid
82
+ // }`
83
+ // );
92
84
  (0, messaging_1.consumeMessage)(parsed, {
93
85
  'load-result': (result) => {
94
86
  if (result.success) {
95
87
  const { name, createNodesPattern } = result;
96
88
  pluginName = name;
97
- pidMap.set(worker.pid, name);
89
+ const pending = new Set();
90
+ pidMap.set(worker.pid, { name, pending });
98
91
  onload({
99
92
  name,
100
93
  createNodes: createNodesPattern
101
94
  ? [
102
95
  createNodesPattern,
103
96
  (configFiles, ctx) => {
104
- return new Promise((res, rej) => {
97
+ return new Promise(function (res, rej) {
98
+ const tx = pluginName + ':createNodes:' + performance.now();
105
99
  worker.send((0, messaging_1.createMessage)({
106
100
  type: 'createNodes',
107
- payload: { configFiles, context: ctx },
101
+ payload: { configFiles, context: ctx, tx },
108
102
  }));
109
- createNodesResolver = res;
110
- createNodesRejecter = rej;
103
+ pending.add(tx);
104
+ promiseBank.set(tx, {
105
+ promise: this,
106
+ resolver: res,
107
+ rejecter: rej,
108
+ });
111
109
  });
112
110
  },
113
111
  ]
114
112
  : undefined,
115
113
  createDependencies: result.hasCreateDependencies
116
114
  ? (opts, ctx) => {
117
- return new Promise((res, rej) => {
115
+ return new Promise(function (res, rej) {
116
+ const tx = pluginName + ':createNodes:' + performance.now();
118
117
  worker.send((0, messaging_1.createMessage)({
119
118
  type: 'createDependencies',
120
- payload: { context: ctx },
119
+ payload: { context: ctx, tx },
121
120
  }));
122
- createDependenciesResolver = res;
123
- createDependenciesRejecter = rej;
121
+ pending.add(tx);
122
+ promiseBank.set(tx, {
123
+ promise: this,
124
+ resolver: res,
125
+ rejecter: rej,
126
+ });
124
127
  });
125
128
  }
126
129
  : undefined,
127
130
  processProjectGraph: result.hasProcessProjectGraph
128
131
  ? (graph, ctx) => {
129
- return new Promise((res, rej) => {
132
+ return new Promise(function (res, rej) {
133
+ const tx = pluginName + ':processProjectGraph:' + performance.now();
130
134
  worker.send((0, messaging_1.createMessage)({
131
135
  type: 'processProjectGraph',
132
- payload: { graph, ctx },
136
+ payload: { graph, ctx, tx },
133
137
  }));
134
- processProjectGraphResolver = res;
135
- processProjectGraphRejecter = rej;
138
+ pending.add(tx);
139
+ promiseBank.set(tx, {
140
+ promise: this,
141
+ resolver: res,
142
+ rejecter: rej,
143
+ });
136
144
  });
137
145
  }
138
146
  : undefined,
@@ -142,47 +150,65 @@ function createWorkerHandler(worker, onload, onloadError) {
142
150
  onloadError(result.error);
143
151
  }
144
152
  },
145
- createDependenciesResult: (result) => {
153
+ createDependenciesResult: ({ tx, ...result }) => {
154
+ const { resolver, rejecter } = promiseBank.get(tx);
146
155
  if (result.success) {
147
- createDependenciesResolver(result.dependencies);
148
- createDependenciesResolver = undefined;
156
+ resolver(result.dependencies);
149
157
  }
150
158
  else if (result.success === false) {
151
- createDependenciesRejecter(result.error);
152
- createDependenciesRejecter = undefined;
159
+ rejecter(result.error);
153
160
  }
161
+ pidMap.get(worker.pid)?.pending.delete(tx);
162
+ promiseBank.delete(tx);
154
163
  },
155
- createNodesResult: (payload) => {
156
- if (payload.success) {
157
- createNodesResolver(payload.result);
158
- createNodesResolver = undefined;
164
+ createNodesResult: ({ tx, ...result }) => {
165
+ const { resolver, rejecter } = promiseBank.get(tx);
166
+ if (result.success) {
167
+ resolver(result.result);
159
168
  }
160
- else if (payload.success === false) {
161
- createNodesRejecter(payload.error);
162
- createNodesRejecter = undefined;
169
+ else if (result.success === false) {
170
+ rejecter(result.error);
163
171
  }
172
+ pidMap.get(worker.pid)?.pending.delete(tx);
173
+ promiseBank.delete(tx);
164
174
  },
165
- processProjectGraphResult: (result) => {
175
+ processProjectGraphResult: ({ tx, ...result }) => {
176
+ const { resolver, rejecter } = promiseBank.get(tx);
166
177
  if (result.success) {
167
- processProjectGraphResolver(result.graph);
168
- processProjectGraphResolver = undefined;
178
+ resolver(result.graph);
169
179
  }
170
180
  else if (result.success === false) {
171
- processProjectGraphRejecter(result.error);
172
- processProjectGraphRejecter = undefined;
181
+ rejecter(result.error);
173
182
  }
183
+ pidMap.get(worker.pid)?.pending.delete(tx);
184
+ promiseBank.delete(tx);
174
185
  },
175
186
  });
176
187
  };
177
188
  }
178
- function workerOnExitHandler(worker) {
189
+ function createWorkerExitHandler(worker) {
179
190
  return () => {
180
191
  if (!pluginWorkersShutdown) {
192
+ pidMap.get(worker.pid)?.pending.forEach((tx) => {
193
+ const { rejecter } = promiseBank.get(tx);
194
+ rejecter(new Error(`Plugin worker ${pidMap.get(worker.pid).name ?? worker.pid} exited unexpectedly with code ${worker.exitCode}`));
195
+ });
181
196
  shutdownPluginWorkers();
182
- throw new Error(`[Nx] plugin worker ${pidMap.get(worker.pid) ?? worker.pid} exited unexpectedly`);
183
197
  }
184
198
  };
185
199
  }
186
200
  process.on('exit', () => {
187
- shutdownPluginWorkers();
201
+ if (pool.size) {
202
+ shutdownPluginWorkers();
203
+ }
188
204
  });
205
+ function getPendingPromises(pool, pidMap) {
206
+ const pendingTxs = [];
207
+ for (const p of pool) {
208
+ const { pending } = pidMap.get(p.pid) ?? { pending: new Set() };
209
+ for (const tx of pending) {
210
+ pendingTxs.push(promiseBank.get(tx)?.promise);
211
+ }
212
+ }
213
+ return pendingTxs;
214
+ }
@@ -4,6 +4,7 @@ const installation_directory_1 = require("../../utils/installation-directory");
4
4
  const worker_api_1 = require("./worker-api");
5
5
  const messaging_1 = require("./messaging");
6
6
  const retrieve_workspace_files_1 = require("../utils/retrieve-workspace-files");
7
+ const utils_1 = require("./utils");
7
8
  global.NX_GRAPH_CREATION = true;
8
9
  let plugin;
9
10
  let pluginOptions;
@@ -34,51 +35,48 @@ process.on('message', async (message) => {
34
35
  };
35
36
  }
36
37
  },
37
- shutdown: async () => {
38
- process.exit(0);
39
- },
40
- createNodes: async ({ configFiles, context }) => {
38
+ createNodes: async ({ configFiles, context, tx }) => {
41
39
  try {
42
40
  const result = await runCreateNodesInParallel(configFiles, context);
43
41
  return {
44
42
  type: 'createNodesResult',
45
- payload: { result, success: true },
43
+ payload: { result, success: true, tx },
46
44
  };
47
45
  }
48
46
  catch (e) {
49
47
  return {
50
48
  type: 'createNodesResult',
51
- payload: { success: false, error: e.stack },
49
+ payload: { success: false, error: e.stack, tx },
52
50
  };
53
51
  }
54
52
  },
55
- createDependencies: async (payload) => {
53
+ createDependencies: async ({ context, tx }) => {
56
54
  try {
57
- const result = await plugin.createDependencies(pluginOptions, payload.context);
55
+ const result = await plugin.createDependencies(pluginOptions, context);
58
56
  return {
59
57
  type: 'createDependenciesResult',
60
- payload: { dependencies: result, success: true },
58
+ payload: { dependencies: result, success: true, tx },
61
59
  };
62
60
  }
63
61
  catch (e) {
64
62
  return {
65
63
  type: 'createDependenciesResult',
66
- payload: { success: false, error: e.stack },
64
+ payload: { success: false, error: e.stack, tx },
67
65
  };
68
66
  }
69
67
  },
70
- processProjectGraph: async ({ graph, ctx }) => {
68
+ processProjectGraph: async ({ graph, ctx, tx }) => {
71
69
  try {
72
70
  const result = await plugin.processProjectGraph(graph, ctx);
73
71
  return {
74
72
  type: 'processProjectGraphResult',
75
- payload: { graph: result, success: true },
73
+ payload: { graph: result, success: true, tx },
76
74
  };
77
75
  }
78
76
  catch (e) {
79
77
  return {
80
78
  type: 'processProjectGraphResult',
81
- payload: { success: false, error: e.stack },
79
+ payload: { success: false, error: e.stack, tx },
82
80
  };
83
81
  }
84
82
  },
@@ -99,24 +97,19 @@ async function loadPluginFromWorker(plugin, root) {
99
97
  function runCreateNodesInParallel(configFiles, context) {
100
98
  const promises = configFiles.map((file) => {
101
99
  performance.mark(`${plugin.name}:createNodes:${file} - start`);
102
- const value = plugin.createNodes[1](file, pluginOptions, context);
103
- if (value instanceof Promise) {
104
- return value
105
- .catch((e) => {
106
- performance.mark(`${plugin.name}:createNodes:${file} - end`);
107
- throw new Error(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
108
- })
109
- .then((r) => {
110
- performance.mark(`${plugin.name}:createNodes:${file} - end`);
111
- performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
112
- return { ...r, pluginName: plugin.name, file };
113
- });
114
- }
115
- else {
100
+ // Result is either static or a promise, using Promise.resolve lets us
101
+ // handle both cases with same logic
102
+ const value = Promise.resolve(plugin.createNodes[1](file, pluginOptions, context));
103
+ return value
104
+ .catch((e) => {
105
+ performance.mark(`${plugin.name}:createNodes:${file} - end`);
106
+ throw new utils_1.CreateNodesError(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
107
+ })
108
+ .then((r) => {
116
109
  performance.mark(`${plugin.name}:createNodes:${file} - end`);
117
110
  performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
118
- return { ...value, pluginName: plugin.name, file };
119
- }
111
+ return { ...r, pluginName: plugin.name, file };
112
+ });
120
113
  });
121
114
  return Promise.all(promises);
122
115
  }
@@ -0,0 +1,9 @@
1
+ import type { NxPluginV1 } from '../../utils/nx-plugin.deprecated';
2
+ import type { NormalizedPlugin, RemotePlugin } from './internal-api';
3
+ import type { NxPlugin, NxPluginV2 } from './public-api';
4
+ export declare function isNxPluginV2(plugin: NxPlugin): plugin is NxPluginV2;
5
+ export declare function isNxPluginV1(plugin: NxPlugin | RemotePlugin): plugin is NxPluginV1;
6
+ export declare function normalizeNxPlugin(plugin: NxPlugin): NormalizedPlugin;
7
+ export declare class CreateNodesError extends Error {
8
+ constructor(msg: any, cause: Error | unknown);
9
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateNodesError = exports.normalizeNxPlugin = exports.isNxPluginV1 = exports.isNxPluginV2 = void 0;
4
+ const node_path_1 = require("node:path");
5
+ const workspaces_1 = require("../../config/workspaces");
6
+ const globs_1 = require("../../utils/globs");
7
+ function isNxPluginV2(plugin) {
8
+ return 'createNodes' in plugin || 'createDependencies' in plugin;
9
+ }
10
+ exports.isNxPluginV2 = isNxPluginV2;
11
+ function isNxPluginV1(plugin) {
12
+ return 'processProjectGraph' in plugin || 'projectFilePatterns' in plugin;
13
+ }
14
+ exports.isNxPluginV1 = isNxPluginV1;
15
+ function normalizeNxPlugin(plugin) {
16
+ if (isNxPluginV2(plugin)) {
17
+ return plugin;
18
+ }
19
+ if (isNxPluginV1(plugin) && plugin.projectFilePatterns) {
20
+ return {
21
+ ...plugin,
22
+ createNodes: [
23
+ `*/**/${(0, globs_1.combineGlobPatterns)(plugin.projectFilePatterns)}`,
24
+ (configFilePath) => {
25
+ const root = (0, node_path_1.dirname)(configFilePath);
26
+ return {
27
+ projects: {
28
+ [root]: {
29
+ name: (0, workspaces_1.toProjectName)(configFilePath),
30
+ targets: plugin.registerProjectTargets?.(configFilePath),
31
+ },
32
+ },
33
+ };
34
+ },
35
+ ],
36
+ };
37
+ }
38
+ return plugin;
39
+ }
40
+ exports.normalizeNxPlugin = normalizeNxPlugin;
41
+ class CreateNodesError extends Error {
42
+ constructor(msg, cause) {
43
+ const message = `${msg} ${!cause
44
+ ? ''
45
+ : cause instanceof Error
46
+ ? `\n\n\t Inner Error: ${cause.stack}`
47
+ : cause}`;
48
+ // These errors are thrown during a JS callback which is invoked via rust.
49
+ // The errors messaging gets lost in the rust -> js -> rust transition, but
50
+ // logging the error here will ensure that it is visible in the console.
51
+ console.error(message);
52
+ super(message, { cause });
53
+ }
54
+ }
55
+ exports.CreateNodesError = CreateNodesError;
@@ -15,14 +15,14 @@ const find_project_for_path_1 = require("../utils/find-project-for-path");
15
15
  const path_1 = require("../../utils/path");
16
16
  const logger_1 = require("../../utils/logger");
17
17
  const node_path_1 = require("node:path");
18
- const internal_api_1 = require("./internal-api");
18
+ const utils_1 = require("./utils");
19
19
  async function loadNxPluginAsync(pluginConfiguration, paths, projects, root) {
20
20
  const { plugin: moduleName, options } = typeof pluginConfiguration === 'object'
21
21
  ? pluginConfiguration
22
22
  : { plugin: pluginConfiguration, options: undefined };
23
23
  performance.mark(`Load Nx Plugin: ${moduleName} - start`);
24
24
  let { pluginPath, name } = await getPluginPathAndName(moduleName, paths, projects, root);
25
- const plugin = (0, internal_api_1.normalizeNxPlugin)(await importPluginModule(pluginPath));
25
+ const plugin = (0, utils_1.normalizeNxPlugin)(await importPluginModule(pluginPath));
26
26
  plugin.name ??= name;
27
27
  performance.mark(`Load Nx Plugin: ${moduleName} - end`);
28
28
  performance.measure(`Load Nx Plugin: ${moduleName}`, `Load Nx Plugin: ${moduleName} - start`, `Load Nx Plugin: ${moduleName} - end`);
@@ -7,6 +7,8 @@ const workspace_root_1 = require("../../utils/workspace-root");
7
7
  const target_defaults_plugin_1 = require("../../plugins/target-defaults/target-defaults-plugin");
8
8
  const minimatch_1 = require("minimatch");
9
9
  const path_1 = require("path");
10
+ const utils_1 = require("../plugins/utils");
11
+ const plugin_pool_1 = require("../plugins/plugin-pool");
10
12
  function mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInformation,
11
13
  // This function is used when reading project configuration
12
14
  // in generators, where we don't want to do this.
@@ -146,16 +148,13 @@ plugins, root = workspace_root_1.workspaceRoot) {
146
148
  matchedFiles.push(file);
147
149
  }
148
150
  }
149
- try {
150
- let r = createNodes(matchedFiles, {
151
- nxJsonConfiguration: nxJson,
152
- workspaceRoot: root,
153
- });
154
- results.push(r);
155
- }
156
- catch (e) {
157
- throw new CreateNodesError(`Unable to create nodes using plugin ${plugin.name}.`, e);
158
- }
151
+ let r = createNodes(matchedFiles, {
152
+ nxJsonConfiguration: nxJson,
153
+ workspaceRoot: root,
154
+ }).catch((e) => (0, plugin_pool_1.shutdownPluginWorkers)().then(() => {
155
+ throw e;
156
+ }));
157
+ results.push(r);
159
158
  }
160
159
  return Promise.all(results).then((results) => {
161
160
  performance.mark('createNodes:merge - start');
@@ -173,7 +172,7 @@ plugins, root = workspace_root_1.workspaceRoot) {
173
172
  mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, [file, pluginName]);
174
173
  }
175
174
  catch (e) {
176
- throw new CreateNodesError(`Unable to merge project information for "${project.root}" from ${result.file} using plugin ${result.pluginName}.`, e);
175
+ throw new utils_1.CreateNodesError(`Unable to merge project information for "${project.root}" from ${result.file} using plugin ${result.pluginName}.`, e);
177
176
  }
178
177
  }
179
178
  Object.assign(externalNodes, pluginExternalNodes);
@@ -229,20 +228,6 @@ function readProjectConfigurationsFromRootMap(projectRootMap) {
229
228
  return projects;
230
229
  }
231
230
  exports.readProjectConfigurationsFromRootMap = readProjectConfigurationsFromRootMap;
232
- class CreateNodesError extends Error {
233
- constructor(msg, cause) {
234
- const message = `${msg} ${!cause
235
- ? ''
236
- : cause instanceof Error
237
- ? `\n\n\t Inner Error: ${cause.stack}`
238
- : cause}`;
239
- // These errors are thrown during a JS callback which is invoked via rust.
240
- // The errors messaging gets lost in the rust -> js -> rust transition, but
241
- // logging the error here will ensure that it is visible in the console.
242
- console.error(message);
243
- super(message, { cause });
244
- }
245
- }
246
231
  /**
247
232
  * Merges two targets.
248
233
  *