nx 20.4.0-canary.20250124-45847a6 → 20.4.0-rc.0

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 (36) hide show
  1. package/package.json +11 -11
  2. package/src/command-line/release/config/conventional-commits.js +7 -0
  3. package/src/command-line/release/publish.js +11 -0
  4. package/src/command-line/release/utils/git.js +6 -1
  5. package/src/core/graph/main.js +1 -1
  6. package/src/core/graph/styles.js +1 -1
  7. package/src/daemon/client/client.d.ts +3 -0
  8. package/src/daemon/client/client.js +15 -0
  9. package/src/daemon/message-types/run-tasks-execution-hooks.d.ts +13 -0
  10. package/src/daemon/message-types/run-tasks-execution-hooks.js +19 -0
  11. package/src/daemon/server/handle-tasks-execution-hooks.d.ts +19 -0
  12. package/src/daemon/server/handle-tasks-execution-hooks.js +35 -0
  13. package/src/daemon/server/server.js +8 -0
  14. package/src/devkit-exports.d.ts +6 -2
  15. package/src/native/nx.wasm32-wasi.wasm +0 -0
  16. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +1 -4
  17. package/src/plugins/js/utils/packages.js +2 -16
  18. package/src/project-graph/plugins/get-plugins.js +2 -17
  19. package/src/project-graph/plugins/isolation/enabled.d.ts +1 -0
  20. package/src/project-graph/plugins/isolation/enabled.js +19 -0
  21. package/src/project-graph/plugins/isolation/messaging.d.ts +46 -7
  22. package/src/project-graph/plugins/isolation/messaging.js +5 -1
  23. package/src/project-graph/plugins/isolation/plugin-pool.js +46 -0
  24. package/src/project-graph/plugins/isolation/plugin-worker.js +40 -0
  25. package/src/project-graph/plugins/load-resolved-plugin.js +4 -1
  26. package/src/project-graph/plugins/loaded-nx-plugin.d.ts +3 -5
  27. package/src/project-graph/plugins/loaded-nx-plugin.js +27 -0
  28. package/src/project-graph/plugins/public-api.d.ts +26 -6
  29. package/src/project-graph/plugins/tasks-execution-hooks.d.ts +3 -0
  30. package/src/project-graph/plugins/tasks-execution-hooks.js +65 -0
  31. package/src/project-graph/utils/retrieve-workspace-files.js +1 -1
  32. package/src/tasks-runner/forked-process-task-runner.js +8 -30
  33. package/src/tasks-runner/life-cycle.d.ts +7 -0
  34. package/src/tasks-runner/run-command.d.ts +2 -4
  35. package/src/tasks-runner/run-command.js +18 -2
  36. package/src/tasks-runner/task-orchestrator.js +6 -2
@@ -1 +1 @@
1
- "use strict";(self.webpackChunk=self.webpackChunk||[]).push([[532],{69552:()=>{}},s=>{var e;e=69552,s(s.s=e)}]);
1
+ "use strict";(self.webpackChunk=self.webpackChunk||[]).push([[532],{6395:()=>{}},s=>{var e;e=6395,s(s.s=e)}]);
@@ -5,6 +5,7 @@ import { Task, TaskGraph } from '../../config/task-graph';
5
5
  import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils';
6
6
  import { NxWorkspaceFiles, TaskRun, TaskTarget } from '../../native';
7
7
  import type { FlushSyncGeneratorChangesResult, SyncGeneratorRunResult } from '../../utils/sync-generators';
8
+ import { PostTasksExecutionContext, PreTasksExecutionContext } from '../../project-graph/plugins/public-api';
8
9
  export type UnregisterCallback = () => void;
9
10
  export type ChangedFile = {
10
11
  path: string;
@@ -60,6 +61,8 @@ export declare class DaemonClient {
60
61
  taskGenerators: string[];
61
62
  }>;
62
63
  updateWorkspaceContext(createdFiles: string[], updatedFiles: string[], deletedFiles: string[]): Promise<void>;
64
+ runPreTasksExecution(context: PreTasksExecutionContext): Promise<NodeJS.ProcessEnv[]>;
65
+ runPostTasksExecution(context: PostTasksExecutionContext): Promise<void>;
63
66
  isServerAvailable(): Promise<boolean>;
64
67
  private sendToDaemonViaQueue;
65
68
  private setUpConnection;
@@ -31,6 +31,7 @@ const get_registered_sync_generators_1 = require("../message-types/get-registere
31
31
  const update_workspace_context_1 = require("../message-types/update-workspace-context");
32
32
  const flush_sync_generator_changes_to_disk_1 = require("../message-types/flush-sync-generator-changes-to-disk");
33
33
  const delayed_spinner_1 = require("../../utils/delayed-spinner");
34
+ const run_tasks_execution_hooks_1 = require("../message-types/run-tasks-execution-hooks");
34
35
  const DAEMON_ENV_SETTINGS = {
35
36
  NX_PROJECT_GLOB_CACHE: 'false',
36
37
  NX_CACHE_PROJECTS_CONFIG: 'false',
@@ -292,6 +293,20 @@ class DaemonClient {
292
293
  };
293
294
  return this.sendToDaemonViaQueue(message);
294
295
  }
296
+ async runPreTasksExecution(context) {
297
+ const message = {
298
+ type: run_tasks_execution_hooks_1.PRE_TASKS_EXECUTION,
299
+ context,
300
+ };
301
+ return this.sendToDaemonViaQueue(message);
302
+ }
303
+ async runPostTasksExecution(context) {
304
+ const message = {
305
+ type: run_tasks_execution_hooks_1.POST_TASKS_EXECUTION,
306
+ context,
307
+ };
308
+ return this.sendToDaemonViaQueue(message);
309
+ }
295
310
  async isServerAvailable() {
296
311
  return new Promise((resolve) => {
297
312
  try {
@@ -0,0 +1,13 @@
1
+ import type { PostTasksExecutionContext, PreTasksExecutionContext } from '../../project-graph/plugins';
2
+ export declare const PRE_TASKS_EXECUTION: "PRE_TASKS_EXECUTION";
3
+ export declare const POST_TASKS_EXECUTION: "POST_TASKS_EXECUTION";
4
+ export type HandlePreTasksExecutionMessage = {
5
+ type: typeof PRE_TASKS_EXECUTION;
6
+ context: PreTasksExecutionContext;
7
+ };
8
+ export type HandlePostTasksExecutionMessage = {
9
+ type: typeof POST_TASKS_EXECUTION;
10
+ context: PostTasksExecutionContext;
11
+ };
12
+ export declare function isHandlePreTasksExecutionMessage(message: unknown): message is HandlePreTasksExecutionMessage;
13
+ export declare function isHandlePostTasksExecutionMessage(message: unknown): message is HandlePostTasksExecutionMessage;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST_TASKS_EXECUTION = exports.PRE_TASKS_EXECUTION = void 0;
4
+ exports.isHandlePreTasksExecutionMessage = isHandlePreTasksExecutionMessage;
5
+ exports.isHandlePostTasksExecutionMessage = isHandlePostTasksExecutionMessage;
6
+ exports.PRE_TASKS_EXECUTION = 'PRE_TASKS_EXECUTION';
7
+ exports.POST_TASKS_EXECUTION = 'POST_TASKS_EXECUTION';
8
+ function isHandlePreTasksExecutionMessage(message) {
9
+ return (typeof message === 'object' &&
10
+ message !== null &&
11
+ 'type' in message &&
12
+ message['type'] === exports.PRE_TASKS_EXECUTION);
13
+ }
14
+ function isHandlePostTasksExecutionMessage(message) {
15
+ return (typeof message === 'object' &&
16
+ message !== null &&
17
+ 'type' in message &&
18
+ message['type'] === exports.POST_TASKS_EXECUTION);
19
+ }
@@ -0,0 +1,19 @@
1
+ import type { PostTasksExecutionContext, PreTasksExecutionContext } from '../../project-graph/plugins/public-api';
2
+ export declare function handleRunPreTasksExecution(context: PreTasksExecutionContext): Promise<{
3
+ response: string;
4
+ description: string;
5
+ error?: undefined;
6
+ } | {
7
+ error: any;
8
+ description: string;
9
+ response?: undefined;
10
+ }>;
11
+ export declare function handleRunPostTasksExecution(context: PostTasksExecutionContext): Promise<{
12
+ response: string;
13
+ description: string;
14
+ error?: undefined;
15
+ } | {
16
+ error: any;
17
+ description: string;
18
+ response?: undefined;
19
+ }>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRunPreTasksExecution = handleRunPreTasksExecution;
4
+ exports.handleRunPostTasksExecution = handleRunPostTasksExecution;
5
+ const tasks_execution_hooks_1 = require("../../project-graph/plugins/tasks-execution-hooks");
6
+ async function handleRunPreTasksExecution(context) {
7
+ try {
8
+ const envs = await (0, tasks_execution_hooks_1.runPreTasksExecution)(context);
9
+ return {
10
+ response: JSON.stringify(envs),
11
+ description: 'handleRunPreTasksExecution',
12
+ };
13
+ }
14
+ catch (e) {
15
+ return {
16
+ error: e,
17
+ description: `Error when running preTasksExecution.`,
18
+ };
19
+ }
20
+ }
21
+ async function handleRunPostTasksExecution(context) {
22
+ try {
23
+ await (0, tasks_execution_hooks_1.runPostTasksExecution)(context);
24
+ return {
25
+ response: 'true',
26
+ description: 'handleRunPostTasksExecution',
27
+ };
28
+ }
29
+ catch (e) {
30
+ return {
31
+ error: e,
32
+ description: `Error when running postTasksExecution.`,
33
+ };
34
+ }
35
+ }
@@ -50,6 +50,8 @@ const update_workspace_context_1 = require("../message-types/update-workspace-co
50
50
  const handle_update_workspace_context_1 = require("./handle-update-workspace-context");
51
51
  const flush_sync_generator_changes_to_disk_1 = require("../message-types/flush-sync-generator-changes-to-disk");
52
52
  const handle_flush_sync_generator_changes_to_disk_1 = require("./handle-flush-sync-generator-changes-to-disk");
53
+ const run_tasks_execution_hooks_1 = require("../message-types/run-tasks-execution-hooks");
54
+ const handle_tasks_execution_hooks_1 = require("./handle-tasks-execution-hooks");
53
55
  let performanceObserver;
54
56
  let workspaceWatcherError;
55
57
  let outputsWatcherError;
@@ -163,6 +165,12 @@ async function handleMessage(socket, data) {
163
165
  else if ((0, update_workspace_context_1.isHandleUpdateWorkspaceContextMessage)(payload)) {
164
166
  await handleResult(socket, update_workspace_context_1.UPDATE_WORKSPACE_CONTEXT, () => (0, handle_update_workspace_context_1.handleUpdateWorkspaceContext)(payload.createdFiles, payload.updatedFiles, payload.deletedFiles));
165
167
  }
168
+ else if ((0, run_tasks_execution_hooks_1.isHandlePreTasksExecutionMessage)(payload)) {
169
+ await handleResult(socket, run_tasks_execution_hooks_1.PRE_TASKS_EXECUTION, () => (0, handle_tasks_execution_hooks_1.handleRunPreTasksExecution)(payload.context));
170
+ }
171
+ else if ((0, run_tasks_execution_hooks_1.isHandlePostTasksExecutionMessage)(payload)) {
172
+ await handleResult(socket, run_tasks_execution_hooks_1.POST_TASKS_EXECUTION, () => (0, handle_tasks_execution_hooks_1.handleRunPostTasksExecution)(payload.context));
173
+ }
166
174
  else {
167
175
  await (0, shutdown_utils_1.respondWithErrorAndExit)(socket, `Invalid payload from the client`, new Error(`Unsupported payload sent to daemon server: ${unparsedPayload}`));
168
176
  }
@@ -15,13 +15,17 @@ export type { WorkspaceJsonConfiguration, ProjectsConfigurations, TargetDependen
15
15
  */
16
16
  export type { Generator, GeneratorCallback, PromiseExecutor, AsyncIteratorExecutor, Executor, ExecutorContext, TaskGraphExecutor, GeneratorsJson, ExecutorsJson, MigrationsJson, CustomHasher, HasherContext, } from './config/misc-interfaces';
17
17
  export { workspaceLayout } from './config/configuration';
18
- export type { NxPlugin, NxPluginV2, CreateNodes, CreateNodesFunction, CreateNodesResult, CreateNodesContext, CreateNodesContextV2, CreateNodesFunctionV2, CreateNodesResultV2, CreateNodesV2, CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, ProjectsMetadata, } from './project-graph/plugins';
18
+ export type { NxPlugin, NxPluginV2, CreateNodes, CreateNodesFunction, CreateNodesResult, CreateNodesContext, CreateNodesContextV2, CreateNodesFunctionV2, CreateNodesResultV2, CreateNodesV2, CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, ProjectsMetadata, PreTasksExecution, PreTasksExecutionContext, PostTasksExecution, PostTasksExecutionContext, } from './project-graph/plugins';
19
19
  export { AggregateCreateNodesError } from './project-graph/error-types';
20
20
  export { createNodesFromFiles } from './project-graph/plugins';
21
21
  /**
22
- * @category Workspace
22
+ * @category Tasks
23
23
  */
24
24
  export type { Task, TaskGraph } from './config/task-graph';
25
+ /**
26
+ * @category Tasks
27
+ */
28
+ export type { TaskResult, TaskResults } from './tasks-runner/life-cycle';
25
29
  /**
26
30
  * @category Workspace
27
31
  */
Binary file
@@ -191,10 +191,7 @@ class TargetProjectLocator {
191
191
  }
192
192
  findDependencyInWorkspaceProjects(dep) {
193
193
  this.packageEntryPointsToProjectMap ??= (0, packages_1.getPackageEntryPointsToProjectMap)(this.nodes);
194
- return (this.packageEntryPointsToProjectMap[dep]?.name ??
195
- // if the package exports do not include ".", look for subpath exports
196
- Object.entries(this.packageEntryPointsToProjectMap).find(([entryPoint]) => dep.startsWith(`${entryPoint}/`))?.[1]?.name ??
197
- null);
194
+ return this.packageEntryPointsToProjectMap[dep]?.name ?? null;
198
195
  }
199
196
  resolveImportWithTypescript(normalizedImportExpr, filePath) {
200
197
  let resolvedModule;
@@ -10,28 +10,14 @@ function getPackageEntryPointsToProjectMap(projects) {
10
10
  continue;
11
11
  }
12
12
  const { packageName, packageExports } = metadata.js;
13
- if (!packageExports ||
14
- typeof packageExports === 'string' ||
15
- !Object.keys(packageExports).length) {
13
+ if (!packageExports || typeof packageExports === 'string') {
16
14
  // no `exports` or it points to a file, which would be the equivalent of
17
15
  // an '.' export, in which case the package name is the entry point
18
16
  result[packageName] = project;
19
17
  }
20
18
  else {
21
19
  for (const entryPoint of Object.keys(packageExports)) {
22
- // if entrypoint begins with '.', it is a relative subpath export
23
- // otherwise, it is a conditional export
24
- // https://nodejs.org/api/packages.html#conditional-exports
25
- if (entryPoint.startsWith('.')) {
26
- result[(0, posix_1.join)(packageName, entryPoint)] = project;
27
- }
28
- else {
29
- result[packageName] = project;
30
- }
31
- }
32
- // if there was no '.' entrypoint, ensure the package name is matched with the project
33
- if (!result[packageName]) {
34
- result[packageName] = project;
20
+ result[(0, posix_1.join)(packageName, entryPoint)] = project;
35
21
  }
36
22
  }
37
23
  }
@@ -7,11 +7,11 @@ const node_path_1 = require("node:path");
7
7
  const angular_json_1 = require("../../adapter/angular-json");
8
8
  const nx_json_1 = require("../../config/nx-json");
9
9
  const file_hasher_1 = require("../../hasher/file-hasher");
10
- const native_1 = require("../../native");
11
10
  const workspace_root_1 = require("../../utils/workspace-root");
12
11
  const isolation_1 = require("./isolation");
13
12
  const in_process_loader_1 = require("./in-process-loader");
14
13
  const transpiler_1 = require("./transpiler");
14
+ const enabled_1 = require("./isolation/enabled");
15
15
  /**
16
16
  * Stuff for specified NX Plugins.
17
17
  */
@@ -73,22 +73,7 @@ function cleanupPlugins() {
73
73
  /**
74
74
  * Stuff for generic loading
75
75
  */
76
- function isIsolationEnabled() {
77
- // Explicitly enabled, regardless of further conditions
78
- if (process.env.NX_ISOLATE_PLUGINS === 'true') {
79
- return true;
80
- }
81
- if (
82
- // Explicitly disabled
83
- process.env.NX_ISOLATE_PLUGINS === 'false' ||
84
- // Isolation is disabled on WASM builds currently.
85
- native_1.IS_WASM) {
86
- return false;
87
- }
88
- // Default value
89
- return true;
90
- }
91
- const loadingMethod = isIsolationEnabled()
76
+ const loadingMethod = (0, enabled_1.isIsolationEnabled)()
92
77
  ? isolation_1.loadNxPluginInIsolation
93
78
  : in_process_loader_1.loadNxPlugin;
94
79
  async function loadDefaultNxPlugins(root = workspace_root_1.workspaceRoot) {
@@ -0,0 +1 @@
1
+ export declare function isIsolationEnabled(): boolean;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isIsolationEnabled = isIsolationEnabled;
4
+ const native_1 = require("../../../native");
5
+ function isIsolationEnabled() {
6
+ // Explicitly enabled, regardless of further conditions
7
+ if (process.env.NX_ISOLATE_PLUGINS === 'true') {
8
+ return true;
9
+ }
10
+ if (
11
+ // Explicitly disabled
12
+ process.env.NX_ISOLATE_PLUGINS === 'false' ||
13
+ // Isolation is disabled on WASM builds currently.
14
+ native_1.IS_WASM) {
15
+ return false;
16
+ }
17
+ // Default value
18
+ return true;
19
+ }
@@ -1,9 +1,9 @@
1
- import { ProjectGraph } from '../../../config/project-graph';
2
- import { PluginConfiguration } from '../../../config/nx-json';
3
- import { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2 } from '../public-api';
1
+ import type { ProjectGraph } from '../../../config/project-graph';
2
+ import type { PluginConfiguration } from '../../../config/nx-json';
3
+ import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, PreTasksExecutionContext, PostTasksExecutionContext } from '../public-api';
4
4
  import type { LoadedNxPlugin } from '../loaded-nx-plugin';
5
- import { Serializable } from 'child_process';
6
- import { Socket } from 'net';
5
+ import type { Serializable } from 'child_process';
6
+ import type { Socket } from 'net';
7
7
  export interface PluginWorkerLoadMessage {
8
8
  type: 'load';
9
9
  payload: {
@@ -24,6 +24,8 @@ export interface PluginWorkerLoadResult {
24
24
  hasCreateDependencies: boolean;
25
25
  hasProcessProjectGraph: boolean;
26
26
  hasCreateMetadata: boolean;
27
+ hasPreTasksExecution: boolean;
28
+ hasPostTasksExecution: boolean;
27
29
  success: true;
28
30
  } | {
29
31
  success: false;
@@ -89,8 +91,45 @@ export interface PluginCreateMetadataResult {
89
91
  tx: string;
90
92
  };
91
93
  }
92
- export type PluginWorkerMessage = PluginWorkerLoadMessage | PluginWorkerCreateNodesMessage | PluginCreateDependenciesMessage | PluginCreateMetadataMessage;
93
- export type PluginWorkerResult = PluginWorkerLoadResult | PluginWorkerCreateNodesResult | PluginCreateDependenciesResult | PluginCreateMetadataResult;
94
+ export interface PluginWorkerPreTasksExecutionMessage {
95
+ type: 'preTasksExecution';
96
+ payload: {
97
+ tx: string;
98
+ context: PreTasksExecutionContext;
99
+ };
100
+ }
101
+ export interface PluginWorkerPreTasksExecutionMessageResult {
102
+ type: 'preTasksExecutionResult';
103
+ payload: {
104
+ tx: string;
105
+ success: true;
106
+ mutations: NodeJS.ProcessEnv;
107
+ } | {
108
+ success: false;
109
+ error: Error;
110
+ tx: string;
111
+ };
112
+ }
113
+ export interface PluginWorkerPostTasksExecutionMessage {
114
+ type: 'postTasksExecution';
115
+ payload: {
116
+ tx: string;
117
+ context: PostTasksExecutionContext;
118
+ };
119
+ }
120
+ export interface PluginWorkerPostTasksExecutionMessageResult {
121
+ type: 'postTasksExecutionResult';
122
+ payload: {
123
+ tx: string;
124
+ success: true;
125
+ } | {
126
+ success: false;
127
+ error: Error;
128
+ tx: string;
129
+ };
130
+ }
131
+ export type PluginWorkerMessage = PluginWorkerLoadMessage | PluginWorkerCreateNodesMessage | PluginCreateDependenciesMessage | PluginCreateMetadataMessage | PluginWorkerPreTasksExecutionMessage | PluginWorkerPostTasksExecutionMessage;
132
+ export type PluginWorkerResult = PluginWorkerLoadResult | PluginWorkerCreateNodesResult | PluginCreateDependenciesResult | PluginCreateMetadataResult | PluginWorkerPreTasksExecutionMessageResult | PluginWorkerPostTasksExecutionMessageResult;
94
133
  export declare function isPluginWorkerMessage(message: Serializable): message is PluginWorkerMessage;
95
134
  export declare function isPluginWorkerResult(message: Serializable): message is PluginWorkerResult;
96
135
  type MaybePromise<T> = T | Promise<T>;
@@ -12,9 +12,11 @@ function isPluginWorkerMessage(message) {
12
12
  'load',
13
13
  'createNodes',
14
14
  'createDependencies',
15
- 'processProjectGraph',
16
15
  'createMetadata',
16
+ 'processProjectGraph',
17
17
  'shutdown',
18
+ 'preTasksExecution',
19
+ 'postTasksExecution',
18
20
  ].includes(message.type));
19
21
  }
20
22
  function isPluginWorkerResult(message) {
@@ -27,6 +29,8 @@ function isPluginWorkerResult(message) {
27
29
  'createDependenciesResult',
28
30
  'processProjectGraphResult',
29
31
  'createMetadataResult',
32
+ 'preTasksExecutionResult',
33
+ 'postTasksExecutionResult',
30
34
  ].includes(message.type));
31
35
  }
32
36
  // Takes a message and a map of handlers and calls the appropriate handler
@@ -131,6 +131,34 @@ function createWorkerHandler(worker, pending, onload, onloadError, socket) {
131
131
  });
132
132
  }
133
133
  : undefined,
134
+ preTasksExecution: result.hasPreTasksExecution
135
+ ? (context) => {
136
+ const tx = pluginName + worker.pid + ':preTasksExecution:' + txId++;
137
+ return registerPendingPromise(tx, pending, () => {
138
+ (0, messaging_1.sendMessageOverSocket)(socket, {
139
+ type: 'preTasksExecution',
140
+ payload: { tx, context },
141
+ });
142
+ }, {
143
+ plugin: pluginName,
144
+ operation: 'preTasksExecution',
145
+ });
146
+ }
147
+ : undefined,
148
+ postTasksExecution: result.hasPostTasksExecution
149
+ ? (context) => {
150
+ const tx = pluginName + worker.pid + ':postTasksExecution:' + txId++;
151
+ return registerPendingPromise(tx, pending, () => {
152
+ (0, messaging_1.sendMessageOverSocket)(socket, {
153
+ type: 'postTasksExecution',
154
+ payload: { tx, context },
155
+ });
156
+ }, {
157
+ plugin: pluginName,
158
+ operation: 'postTasksExecution',
159
+ });
160
+ }
161
+ : undefined,
134
162
  });
135
163
  }
136
164
  else if (result.success === false) {
@@ -164,6 +192,24 @@ function createWorkerHandler(worker, pending, onload, onloadError, socket) {
164
192
  rejector(result.error);
165
193
  }
166
194
  },
195
+ preTasksExecutionResult: ({ tx, ...result }) => {
196
+ const { resolver, rejector } = pending.get(tx);
197
+ if (result.success) {
198
+ resolver(result.mutations);
199
+ }
200
+ else if (result.success === false) {
201
+ rejector(result.error);
202
+ }
203
+ },
204
+ postTasksExecutionResult: ({ tx, ...result }) => {
205
+ const { resolver, rejector } = pending.get(tx);
206
+ if (result.success) {
207
+ resolver();
208
+ }
209
+ else if (result.success === false) {
210
+ rejector(result.error);
211
+ }
212
+ },
167
213
  });
168
214
  };
169
215
  }
@@ -51,6 +51,8 @@ const server = (0, net_1.createServer)((socket) => {
51
51
  hasProcessProjectGraph: 'processProjectGraph' in plugin &&
52
52
  !!plugin.processProjectGraph,
53
53
  hasCreateMetadata: 'createMetadata' in plugin && !!plugin.createMetadata,
54
+ hasPreTasksExecution: 'preTasksExecution' in plugin && !!plugin.preTasksExecution,
55
+ hasPostTasksExecution: 'postTasksExecution' in plugin && !!plugin.postTasksExecution,
54
56
  success: true,
55
57
  },
56
58
  };
@@ -122,6 +124,44 @@ const server = (0, net_1.createServer)((socket) => {
122
124
  };
123
125
  }
124
126
  },
127
+ preTasksExecution: async ({ tx, context }) => {
128
+ try {
129
+ const mutations = await plugin.preTasksExecution?.(context);
130
+ return {
131
+ type: 'preTasksExecutionResult',
132
+ payload: { success: true, tx, mutations },
133
+ };
134
+ }
135
+ catch (e) {
136
+ return {
137
+ type: 'preTasksExecutionResult',
138
+ payload: {
139
+ success: false,
140
+ error: (0, serializable_error_1.createSerializableError)(e),
141
+ tx,
142
+ },
143
+ };
144
+ }
145
+ },
146
+ postTasksExecution: async ({ tx, context }) => {
147
+ try {
148
+ await plugin.postTasksExecution?.(context);
149
+ return {
150
+ type: 'postTasksExecutionResult',
151
+ payload: { success: true, tx },
152
+ };
153
+ }
154
+ catch (e) {
155
+ return {
156
+ type: 'postTasksExecutionResult',
157
+ payload: {
158
+ success: false,
159
+ error: (0, serializable_error_1.createSerializableError)(e),
160
+ tx,
161
+ },
162
+ };
163
+ }
164
+ },
125
165
  });
126
166
  }));
127
167
  // There should only ever be one host -> worker connection
@@ -12,7 +12,10 @@ async function importPluginModule(pluginPath) {
12
12
  if (m.default &&
13
13
  ('createNodes' in m.default ||
14
14
  'createNodesV2' in m.default ||
15
- 'createDependencies' in m.default)) {
15
+ 'createDependencies' in m.default ||
16
+ 'createMetadata' in m.default ||
17
+ 'preTasksExecution' in m.default ||
18
+ 'postTasksExecution' in m.default)) {
16
19
  return m.default;
17
20
  }
18
21
  return m;
@@ -1,7 +1,7 @@
1
1
  import type { ProjectGraph } from '../../config/project-graph';
2
2
  import type { PluginConfiguration } from '../../config/nx-json';
3
3
  import type { RawProjectGraphDependency } from '../project-graph-builder';
4
- import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, NxPluginV2, ProjectsMetadata } from './public-api';
4
+ import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, NxPluginV2, PostTasksExecutionContext, PreTasksExecutionContext, ProjectsMetadata } from './public-api';
5
5
  export declare class LoadedNxPlugin {
6
6
  readonly name: string;
7
7
  readonly createNodes?: [
@@ -10,12 +10,10 @@ export declare class LoadedNxPlugin {
10
10
  ];
11
11
  readonly createDependencies?: (context: CreateDependenciesContext) => Promise<RawProjectGraphDependency[]>;
12
12
  readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) => Promise<ProjectsMetadata>;
13
+ readonly preTasksExecution?: (context: PreTasksExecutionContext) => Promise<NodeJS.ProcessEnv>;
14
+ readonly postTasksExecution?: (context: PostTasksExecutionContext) => Promise<void>;
13
15
  readonly options?: unknown;
14
16
  readonly include?: string[];
15
17
  readonly exclude?: string[];
16
18
  constructor(plugin: NxPluginV2, pluginDefinition: PluginConfiguration);
17
19
  }
18
- export type CreateNodesResultWithContext = CreateNodesResult & {
19
- file: string;
20
- pluginName: string;
21
- };
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LoadedNxPlugin = void 0;
4
4
  const error_types_1 = require("../error-types");
5
5
  const utils_1 = require("./utils");
6
+ const enabled_1 = require("./isolation/enabled");
7
+ const client_1 = require("../../daemon/client/client");
6
8
  class LoadedNxPlugin {
7
9
  constructor(plugin, pluginDefinition) {
8
10
  this.name = plugin.name;
@@ -52,6 +54,31 @@ class LoadedNxPlugin {
52
54
  if (plugin.createMetadata) {
53
55
  this.createMetadata = async (graph, context) => plugin.createMetadata(graph, this.options, context);
54
56
  }
57
+ if (plugin.preTasksExecution) {
58
+ this.preTasksExecution = async (context) => {
59
+ const updates = {};
60
+ let revokeFn;
61
+ if ((0, enabled_1.isIsolationEnabled)() || (0, client_1.isDaemonEnabled)()) {
62
+ const { proxy, revoke } = Proxy.revocable(process.env, {
63
+ set: (target, key, value) => {
64
+ target[key] = value;
65
+ updates[key] = value;
66
+ return true;
67
+ },
68
+ });
69
+ process.env = proxy;
70
+ revokeFn = revoke;
71
+ }
72
+ await plugin.preTasksExecution(this.options, context);
73
+ if (revokeFn) {
74
+ revokeFn();
75
+ }
76
+ return updates;
77
+ };
78
+ if (plugin.postTasksExecution) {
79
+ this.postTasksExecution = async (context) => plugin.postTasksExecution(this.options, context);
80
+ }
81
+ }
55
82
  }
56
83
  }
57
84
  exports.LoadedNxPlugin = LoadedNxPlugin;
@@ -1,7 +1,8 @@
1
- import { FileMap, ProjectGraph, ProjectGraphExternalNode } from '../../config/project-graph';
2
- import { ProjectConfiguration } from '../../config/workspace-json-project-json';
3
- import { NxJsonConfiguration } from '../../config/nx-json';
4
- import { RawProjectGraphDependency } from '../project-graph-builder';
1
+ import type { FileMap, ProjectGraph, ProjectGraphExternalNode } from '../../config/project-graph';
2
+ import type { ProjectConfiguration } from '../../config/workspace-json-project-json';
3
+ import type { NxJsonConfiguration } from '../../config/nx-json';
4
+ import type { RawProjectGraphDependency } from '../project-graph-builder';
5
+ import type { TaskResults } from '../../tasks-runner/life-cycle';
5
6
  /**
6
7
  * Context for {@link CreateNodesFunction}
7
8
  */
@@ -96,7 +97,7 @@ export type CreateMetadataContext = {
96
97
  export type ProjectsMetadata = Record<string, Pick<ProjectConfiguration, 'metadata'>>;
97
98
  export type CreateMetadata<T = unknown> = (graph: ProjectGraph, options: T | undefined, context: CreateMetadataContext) => ProjectsMetadata | Promise<ProjectsMetadata>;
98
99
  /**
99
- * A plugin for Nx which creates nodes and dependencies for the {@link ProjectGraph}
100
+ * A plugin which enhances the behavior of Nx
100
101
  */
101
102
  export type NxPluginV2<TOptions = unknown> = {
102
103
  name: string;
@@ -122,8 +123,27 @@ export type NxPluginV2<TOptions = unknown> = {
122
123
  * Provides a function to create metadata for the {@link ProjectGraph}
123
124
  */
124
125
  createMetadata?: CreateMetadata<TOptions>;
126
+ /**
127
+ * Provides a function to run before the Nx runs tasks
128
+ */
129
+ preTasksExecution?: PreTasksExecution<TOptions>;
130
+ /**
131
+ * Provides a function to run after the Nx runs tasks
132
+ */
133
+ postTasksExecution?: PostTasksExecution<TOptions>;
134
+ };
135
+ export type PreTasksExecutionContext = {
136
+ readonly workspaceRoot: string;
137
+ readonly nxJsonConfiguration: NxJsonConfiguration;
138
+ };
139
+ export type PostTasksExecutionContext = {
140
+ readonly workspaceRoot: string;
141
+ readonly nxJsonConfiguration: NxJsonConfiguration;
142
+ readonly taskResults: TaskResults;
125
143
  };
144
+ export type PreTasksExecution<TOptions = unknown> = (options: TOptions | undefined, context: PreTasksExecutionContext) => void | Promise<void>;
145
+ export type PostTasksExecution<TOptions = unknown> = (options: TOptions | undefined, context: PostTasksExecutionContext) => void | Promise<void>;
126
146
  /**
127
- * A plugin for Nx
147
+ * A plugin which enhances the behavior of Nx
128
148
  */
129
149
  export type NxPlugin = NxPluginV2;
@@ -0,0 +1,3 @@
1
+ import type { PostTasksExecutionContext, PreTasksExecutionContext } from './public-api';
2
+ export declare function runPreTasksExecution(pluginContext: PreTasksExecutionContext): Promise<NodeJS.ProcessEnv[]>;
3
+ export declare function runPostTasksExecution(context: PostTasksExecutionContext): Promise<void>;