nx 18.1.0-canary.20240307-84d96cc → 18.1.0-canary.20240309-235ca8c

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 (35) hide show
  1. package/bin/init-local.js +13 -1
  2. package/bin/post-install.js +7 -5
  3. package/package.json +12 -12
  4. package/src/core/graph/3rdpartylicenses.txt +0 -51
  5. package/src/core/graph/main.js +1 -1
  6. package/src/core/graph/polyfills.js +1 -1
  7. package/src/core/graph/runtime.js +1 -1
  8. package/src/core/graph/styles.js +1 -1
  9. package/src/daemon/server/plugins.d.ts +3 -0
  10. package/src/daemon/server/plugins.js +22 -0
  11. package/src/daemon/server/project-graph-incremental-recomputation.js +8 -6
  12. package/src/daemon/server/shutdown-utils.js +2 -0
  13. package/src/devkit-internals.d.ts +0 -1
  14. package/src/devkit-internals.js +1 -3
  15. package/src/executors/utils/convert-nx-executor.js +4 -1
  16. package/src/migrations/update-15-1-0/set-project-names.js +1 -3
  17. package/src/migrations/update-17-2-0/move-default-base.d.ts +1 -1
  18. package/src/migrations/update-17-2-0/move-default-base.js +2 -2
  19. package/src/project-graph/affected/locators/project-glob-changes.js +2 -1
  20. package/src/project-graph/build-project-graph.d.ts +2 -1
  21. package/src/project-graph/build-project-graph.js +5 -9
  22. package/src/project-graph/plugins/internal-api.d.ts +7 -3
  23. package/src/project-graph/plugins/internal-api.js +27 -11
  24. package/src/project-graph/plugins/plugin-pool.d.ts +1 -2
  25. package/src/project-graph/plugins/plugin-pool.js +38 -62
  26. package/src/project-graph/plugins/plugin-worker.js +2 -16
  27. package/src/project-graph/plugins/worker-api.d.ts +8 -6
  28. package/src/project-graph/plugins/worker-api.js +33 -15
  29. package/src/project-graph/project-graph.js +19 -12
  30. package/src/project-graph/utils/project-configuration-utils.js +1 -4
  31. package/src/project-graph/utils/retrieve-workspace-files.d.ts +4 -10
  32. package/src/project-graph/utils/retrieve-workspace-files.js +8 -13
  33. package/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.js +16 -13
  34. package/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.js +8 -7
  35. package/src/utils/plugins/plugin-capabilities.js +4 -4
@@ -1 +1 @@
1
- (()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return r[e].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=r,e=[],o.O=(r,t,n,i)=>{if(!t){var l=1/0;for(f=0;f<e.length;f++){for(var[t,n,i]=e[f],a=!0,u=0;u<t.length;u++)(!1&i||l>=i)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(a=!1,i<l&&(l=i));if(a){e.splice(f--,1);var d=n();void 0!==d&&(r=d)}}return r}i=i||0;for(var f=e.length;f>0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[t,n,i]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={2:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,i,[l,a,u]=t,d=0;if(l.some((r=>0!==e[r]))){for(n in a)o.o(a,n)&&(o.m[n]=a[n]);if(u)var f=u(o)}for(r&&r(t);d<l.length;d++)i=l[d],o.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return o.O(f)},t=self.webpackChunk=self.webpackChunk||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();
1
+ (()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return r[e].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=r,e=[],o.O=(r,t,n,i)=>{if(!t){var l=1/0;for(f=0;f<e.length;f++){for(var[t,n,i]=e[f],a=!0,u=0;u<t.length;u++)(!1&i||l>=i)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(a=!1,i<l&&(l=i));if(a){e.splice(f--,1);var d=n();void 0!==d&&(r=d)}}return r}i=i||0;for(var f=e.length;f>0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[t,n,i]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={666:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,i,[l,a,u]=t,d=0;if(l.some((r=>0!==e[r]))){for(n in a)o.o(a,n)&&(o.m[n]=a[n]);if(u)var f=u(o)}for(r&&r(t);d<l.length;d++)i=l[d],o.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return o.O(f)},t=self.webpackChunk=self.webpackChunk||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();
@@ -1 +1 @@
1
- "use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3],{22232:(s,e,k)=>{k.r(e)}},s=>{var e;e=22232,s(s.s=e)}]);
1
+ "use strict";(self.webpackChunk=self.webpackChunk||[]).push([[532],{22232:()=>{}},s=>{var e;e=22232,s(s.s=e)}]);
@@ -0,0 +1,3 @@
1
+ import { RemotePlugin } from '../../project-graph/plugins/internal-api';
2
+ export declare function getPlugins(): Promise<RemotePlugin[]>;
3
+ export declare function cleanupPlugins(): void;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanupPlugins = exports.getPlugins = void 0;
4
+ const nx_json_1 = require("../../config/nx-json");
5
+ const internal_api_1 = require("../../project-graph/plugins/internal-api");
6
+ const workspace_root_1 = require("../../utils/workspace-root");
7
+ let loadedPlugins;
8
+ let cleanup;
9
+ async function getPlugins() {
10
+ if (loadedPlugins) {
11
+ return loadedPlugins;
12
+ }
13
+ const pluginsConfiguration = (0, nx_json_1.readNxJson)().plugins ?? [];
14
+ const [result, cleanupFn] = await (0, internal_api_1.loadNxPluginsInIsolation)(pluginsConfiguration, workspace_root_1.workspaceRoot);
15
+ cleanup = cleanupFn;
16
+ return result;
17
+ }
18
+ exports.getPlugins = getPlugins;
19
+ function cleanupPlugins() {
20
+ cleanup();
21
+ }
22
+ exports.cleanupPlugins = cleanupPlugins;
@@ -13,6 +13,7 @@ const workspace_context_1 = require("../../utils/workspace-context");
13
13
  const workspace_root_1 = require("../../utils/workspace-root");
14
14
  const file_watcher_sockets_1 = require("./file-watching/file-watcher-sockets");
15
15
  const logger_1 = require("./logger");
16
+ const plugins_1 = require("./plugins");
16
17
  let cachedSerializedProjectGraphPromise;
17
18
  const collectedUpdatedFiles = new Set();
18
19
  const collectedDeletedFiles = new Set();
@@ -30,15 +31,16 @@ async function getCachedSerializedProjectGraphPromise() {
30
31
  // reset the wait time
31
32
  waitPeriod = 100;
32
33
  await resetInternalStateIfNxDepsMissing();
34
+ const plugins = await (0, plugins_1.getPlugins)();
33
35
  if (collectedUpdatedFiles.size == 0 && collectedDeletedFiles.size == 0) {
34
36
  if (!cachedSerializedProjectGraphPromise) {
35
37
  cachedSerializedProjectGraphPromise =
36
- processFilesAndCreateAndSerializeProjectGraph();
38
+ processFilesAndCreateAndSerializeProjectGraph(plugins);
37
39
  }
38
40
  }
39
41
  else {
40
42
  cachedSerializedProjectGraphPromise =
41
- processFilesAndCreateAndSerializeProjectGraph();
43
+ processFilesAndCreateAndSerializeProjectGraph(plugins);
42
44
  }
43
45
  return await cachedSerializedProjectGraphPromise;
44
46
  }
@@ -77,7 +79,7 @@ function addUpdatedAndDeletedFiles(createdFiles, updatedFiles, deletedFiles) {
77
79
  waitPeriod = waitPeriod * 2;
78
80
  }
79
81
  cachedSerializedProjectGraphPromise =
80
- processFilesAndCreateAndSerializeProjectGraph();
82
+ processFilesAndCreateAndSerializeProjectGraph(await (0, plugins_1.getPlugins)());
81
83
  await cachedSerializedProjectGraphPromise;
82
84
  if (createdFiles.length > 0) {
83
85
  (0, file_watcher_sockets_1.notifyFileWatcherSockets)(createdFiles, null, null);
@@ -125,7 +127,7 @@ async function processCollectedUpdatedAndDeletedFiles({ projects, externalNodes,
125
127
  throw e;
126
128
  }
127
129
  }
128
- async function processFilesAndCreateAndSerializeProjectGraph() {
130
+ async function processFilesAndCreateAndSerializeProjectGraph(plugins) {
129
131
  try {
130
132
  perf_hooks_1.performance.mark('hash-watched-changes-start');
131
133
  const updatedFiles = [...collectedUpdatedFiles.values()];
@@ -138,7 +140,7 @@ async function processFilesAndCreateAndSerializeProjectGraph() {
138
140
  logger_1.serverLogger.requestLog([...deletedFiles]);
139
141
  const nxJson = (0, nx_json_1.readNxJson)(workspace_root_1.workspaceRoot);
140
142
  global.NX_GRAPH_CREATION = true;
141
- const graphNodes = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(workspace_root_1.workspaceRoot, nxJson);
143
+ const graphNodes = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, workspace_root_1.workspaceRoot, nxJson);
142
144
  await processCollectedUpdatedAndDeletedFiles(graphNodes, updatedFileHashes, deletedFiles);
143
145
  const g = createAndSerializeProjectGraph(graphNodes);
144
146
  delete global.NX_GRAPH_CREATION;
@@ -175,7 +177,7 @@ async function createAndSerializeProjectGraph({ projects, sourceMaps, }) {
175
177
  const fileMap = copyFileMap(exports.fileMapWithFiles.fileMap);
176
178
  const allWorkspaceFiles = copyFileData(exports.fileMapWithFiles.allWorkspaceFiles);
177
179
  const rustReferences = exports.fileMapWithFiles.rustReferences;
178
- const { projectGraph, projectFileMapCache } = await (0, build_project_graph_1.buildProjectGraphUsingProjectFileMap)(projects, knownExternalNodes, fileMap, allWorkspaceFiles, rustReferences, exports.currentProjectFileMapCache || (0, nx_deps_cache_1.readFileMapCache)(), true);
180
+ const { projectGraph, projectFileMapCache } = await (0, build_project_graph_1.buildProjectGraphUsingProjectFileMap)(projects, knownExternalNodes, fileMap, allWorkspaceFiles, rustReferences, exports.currentProjectFileMapCache || (0, nx_deps_cache_1.readFileMapCache)(), true, await (0, plugins_1.getPlugins)());
179
181
  exports.currentProjectFileMapCache = projectFileMapCache;
180
182
  exports.currentProjectGraph = projectGraph;
181
183
  perf_hooks_1.performance.mark('create-project-graph-end');
@@ -5,6 +5,7 @@ const workspace_root_1 = require("../../utils/workspace-root");
5
5
  const logger_1 = require("./logger");
6
6
  const socket_utils_1 = require("../socket-utils");
7
7
  const cache_1 = require("../cache");
8
+ const plugins_1 = require("./plugins");
8
9
  exports.SERVER_INACTIVITY_TIMEOUT_MS = 10800000; // 10800000 ms = 3 hours
9
10
  let watcherInstance;
10
11
  function storeWatcherInstance(instance) {
@@ -28,6 +29,7 @@ async function handleServerProcessTermination({ server, reason, }) {
28
29
  try {
29
30
  server.close();
30
31
  (0, cache_1.deleteDaemonJsonProcessCache)();
32
+ (0, plugins_1.cleanupPlugins)();
31
33
  if (watcherInstance) {
32
34
  await watcherInstance.stop();
33
35
  logger_1.serverLogger.watcherLog(`Stopping the watcher for ${workspace_root_1.workspaceRoot} (sources)`);
@@ -18,4 +18,3 @@ export { hashObject } from './hasher/file-hasher';
18
18
  export { hashWithWorkspaceContext } from './utils/workspace-context';
19
19
  export { createProjectRootMappingsFromProjectConfigurations, findProjectForPath, } from './project-graph/utils/find-project-for-path';
20
20
  export { registerTsProject } from './plugins/js/utils/register';
21
- export { shutdownPluginWorkers } from './project-graph/plugins/plugin-pool';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shutdownPluginWorkers = exports.registerTsProject = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
3
+ exports.registerTsProject = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
4
4
  /**
5
5
  * Note to developers: STOP! These exports are available via requireNx in @nx/devkit.
6
6
  *
@@ -37,5 +37,3 @@ Object.defineProperty(exports, "createProjectRootMappingsFromProjectConfiguratio
37
37
  Object.defineProperty(exports, "findProjectForPath", { enumerable: true, get: function () { return find_project_for_path_1.findProjectForPath; } });
38
38
  var register_1 = require("./plugins/js/utils/register");
39
39
  Object.defineProperty(exports, "registerTsProject", { enumerable: true, get: function () { return register_1.registerTsProject; } });
40
- var plugin_pool_1 = require("./project-graph/plugins/plugin-pool");
41
- Object.defineProperty(exports, "shutdownPluginWorkers", { enumerable: true, get: function () { return plugin_pool_1.shutdownPluginWorkers; } });
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.convertNxExecutor = void 0;
7
7
  const nx_json_1 = require("../../config/nx-json");
8
8
  const retrieve_workspace_files_1 = require("../../project-graph/utils/retrieve-workspace-files");
9
+ const internal_api_1 = require("../../project-graph/plugins/internal-api");
9
10
  /**
10
11
  * Convert an Nx Executor into an Angular Devkit Builder
11
12
  *
@@ -15,10 +16,12 @@ function convertNxExecutor(executor) {
15
16
  const builderFunction = (options, builderContext) => {
16
17
  const promise = async () => {
17
18
  const nxJsonConfiguration = (0, nx_json_1.readNxJson)(builderContext.workspaceRoot);
19
+ const [plugins, cleanup] = await (0, internal_api_1.loadNxPluginsInIsolation)(nxJsonConfiguration.plugins, builderContext.workspaceRoot);
18
20
  const projectsConfigurations = {
19
21
  version: 2,
20
- projects: (await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(builderContext.workspaceRoot, nxJsonConfiguration)).projects,
22
+ projects: (await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)(plugins, builderContext.workspaceRoot, nxJsonConfiguration)).projects,
21
23
  };
24
+ cleanup();
22
25
  const context = {
23
26
  root: builderContext.workspaceRoot,
24
27
  projectName: builderContext.target.project,
@@ -6,11 +6,9 @@ const json_1 = require("../../generators/utils/json");
6
6
  const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
7
7
  const retrieve_workspace_files_1 = require("../../project-graph/utils/retrieve-workspace-files");
8
8
  const internal_api_1 = require("../../project-graph/plugins/internal-api");
9
- const plugin_pool_1 = require("../../project-graph/plugins/plugin-pool");
10
9
  async function default_1(tree) {
11
10
  const nxJson = (0, nx_json_1.readNxJson)(tree);
12
- const projectFiles = await (0, retrieve_workspace_files_1.retrieveProjectConfigurationPaths)(tree.root, await (0, internal_api_1.loadNxPlugins)(nxJson?.plugins));
13
- await (0, plugin_pool_1.shutdownPluginWorkers)();
11
+ const projectFiles = (0, retrieve_workspace_files_1.retrieveProjectConfigurationPaths)(tree.root, (await (0, internal_api_1.loadPlugins)(nxJson?.plugins ?? [], tree.root)).map((p) => p.plugin));
14
12
  const projectJsons = projectFiles.filter((f) => f.endsWith('project.json'));
15
13
  for (let f of projectJsons) {
16
14
  const projectJson = (0, json_1.readJson)(tree, f);
@@ -2,4 +2,4 @@ import { Tree } from '../../generators/tree';
2
2
  /**
3
3
  * Updates existing workspaces to move nx.json's affected.defaultBase to nx.json's base.
4
4
  */
5
- export default function update(host: Tree): void;
5
+ export default function update(host: Tree): Promise<void>;
@@ -6,7 +6,7 @@ const format_changed_files_with_prettier_if_available_1 = require("../../generat
6
6
  /**
7
7
  * Updates existing workspaces to move nx.json's affected.defaultBase to nx.json's base.
8
8
  */
9
- function update(host) {
9
+ async function update(host) {
10
10
  const nxJson = (0, nx_json_1.readNxJson)(host);
11
11
  if (nxJson?.affected?.defaultBase) {
12
12
  nxJson.defaultBase = nxJson.affected.defaultBase;
@@ -16,6 +16,6 @@ function update(host) {
16
16
  }
17
17
  (0, nx_json_1.updateNxJson)(host, nxJson);
18
18
  }
19
- (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(host);
19
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(host);
20
20
  }
21
21
  exports.default = update;
@@ -9,7 +9,8 @@ const retrieve_workspace_files_1 = require("../../utils/retrieve-workspace-files
9
9
  const internal_api_1 = require("../../plugins/internal-api");
10
10
  const globs_1 = require("../../../utils/globs");
11
11
  const getTouchedProjectsFromProjectGlobChanges = async (touchedFiles, projectGraphNodes, nxJson) => {
12
- const globPattern = (0, globs_1.combineGlobPatterns)((0, retrieve_workspace_files_1.configurationGlobs)(await (0, internal_api_1.loadNxPlugins)(nxJson?.plugins, workspace_root_1.workspaceRoot)));
12
+ const plugins = await (0, internal_api_1.loadPlugins)(nxJson?.plugins ?? [], workspace_root_1.workspaceRoot);
13
+ const globPattern = (0, globs_1.combineGlobPatterns)((0, retrieve_workspace_files_1.configurationGlobs)(plugins.map((p) => p.plugin)));
13
14
  const touchedProjects = new Set();
14
15
  for (const touchedFile of touchedFiles) {
15
16
  const isProjectFile = (0, minimatch_1.minimatch)(touchedFile.file, globPattern, {
@@ -1,5 +1,6 @@
1
1
  import { FileData } from './file-utils';
2
2
  import { FileMapCache } from './nx-deps-cache';
3
+ import { RemotePlugin } from './plugins/internal-api';
3
4
  import { FileMap, ProjectGraph, ProjectGraphExternalNode } from '../config/project-graph';
4
5
  import { ProjectConfiguration } from '../config/workspace-json-project-json';
5
6
  import { NxWorkspaceFilesExternals } from '../native';
@@ -8,7 +9,7 @@ export declare function getFileMap(): {
8
9
  allWorkspaceFiles: FileData[];
9
10
  rustReferences: NxWorkspaceFilesExternals | null;
10
11
  };
11
- export declare function buildProjectGraphUsingProjectFileMap(projects: Record<string, ProjectConfiguration>, externalNodes: Record<string, ProjectGraphExternalNode>, fileMap: FileMap, allWorkspaceFiles: FileData[], rustReferences: NxWorkspaceFilesExternals, fileMapCache: FileMapCache | null, shouldWriteCache: boolean): Promise<{
12
+ export declare function buildProjectGraphUsingProjectFileMap(projects: Record<string, ProjectConfiguration>, externalNodes: Record<string, ProjectGraphExternalNode>, fileMap: FileMap, allWorkspaceFiles: FileData[], rustReferences: NxWorkspaceFilesExternals, fileMapCache: FileMapCache | null, shouldWriteCache: boolean, plugins: RemotePlugin[]): Promise<{
12
13
  projectGraph: ProjectGraph;
13
14
  projectFileMapCache: FileMapCache;
14
15
  }>;
@@ -8,7 +8,6 @@ const assert_workspace_validity_1 = require("../utils/assert-workspace-validity"
8
8
  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
- const internal_api_1 = require("./plugins/internal-api");
12
11
  const utils_1 = require("./plugins/utils");
13
12
  const typescript_1 = require("../plugins/js/utils/typescript");
14
13
  const fileutils_1 = require("../utils/fileutils");
@@ -16,7 +15,6 @@ const project_graph_builder_1 = require("./project-graph-builder");
16
15
  const configuration_1 = require("../config/configuration");
17
16
  const fs_1 = require("fs");
18
17
  const output_1 = require("../utils/output");
19
- const plugin_pool_1 = require("./plugins/plugin-pool");
20
18
  let storedFileMap = null;
21
19
  let storedAllWorkspaceFiles = null;
22
20
  let storedRustReferences = null;
@@ -40,7 +38,7 @@ function getFileMap() {
40
38
  }
41
39
  }
42
40
  exports.getFileMap = getFileMap;
43
- async function buildProjectGraphUsingProjectFileMap(projects, externalNodes, fileMap, allWorkspaceFiles, rustReferences, fileMapCache, shouldWriteCache) {
41
+ async function buildProjectGraphUsingProjectFileMap(projects, externalNodes, fileMap, allWorkspaceFiles, rustReferences, fileMapCache, shouldWriteCache, plugins) {
44
42
  storedFileMap = fileMap;
45
43
  storedAllWorkspaceFiles = allWorkspaceFiles;
46
44
  storedRustReferences = rustReferences;
@@ -66,12 +64,11 @@ async function buildProjectGraphUsingProjectFileMap(projects, externalNodes, fil
66
64
  };
67
65
  }
68
66
  const context = createContext(projects, nxJson, externalNodes, fileMap, filesToProcess);
69
- let projectGraph = await buildProjectGraphUsingContext(nxJson, externalNodes, context, cachedFileData, projectGraphVersion);
67
+ let projectGraph = await buildProjectGraphUsingContext(nxJson, externalNodes, context, cachedFileData, projectGraphVersion, plugins);
70
68
  const projectFileMapCache = (0, nx_deps_cache_1.createProjectFileMapCache)(nxJson, packageJsonDeps, fileMap, rootTsConfig);
71
69
  if (shouldWriteCache) {
72
70
  (0, nx_deps_cache_1.writeCache)(projectFileMapCache, projectGraph);
73
71
  }
74
- await (0, plugin_pool_1.shutdownPluginWorkers)();
75
72
  return {
76
73
  projectGraph,
77
74
  projectFileMapCache,
@@ -94,7 +91,7 @@ function readCombinedDeps() {
94
91
  ...installationPackageJson.devDependencies,
95
92
  };
96
93
  }
97
- async function buildProjectGraphUsingContext(nxJson, knownExternalNodes, ctx, cachedFileData, projectGraphVersion) {
94
+ async function buildProjectGraphUsingContext(nxJson, knownExternalNodes, ctx, cachedFileData, projectGraphVersion, plugins) {
98
95
  perf_hooks_1.performance.mark('build project graph:start');
99
96
  const builder = new project_graph_builder_1.ProjectGraphBuilder(null, ctx.fileMap.projectFileMap);
100
97
  builder.setVersion(projectGraphVersion);
@@ -103,7 +100,7 @@ async function buildProjectGraphUsingContext(nxJson, knownExternalNodes, ctx, ca
103
100
  }
104
101
  await (0, normalize_project_nodes_1.normalizeProjectNodes)(ctx, builder);
105
102
  const initProjectGraph = builder.getUpdatedProjectGraph();
106
- const r = await updateProjectGraphWithPlugins(ctx, initProjectGraph);
103
+ const r = await updateProjectGraphWithPlugins(ctx, initProjectGraph, plugins);
107
104
  const updatedBuilder = new project_graph_builder_1.ProjectGraphBuilder(r, ctx.fileMap.projectFileMap);
108
105
  for (const proj of Object.keys(cachedFileData.projectFileMap)) {
109
106
  for (const f of ctx.fileMap.projectFileMap[proj] || []) {
@@ -141,8 +138,7 @@ function createContext(projects, nxJson, externalNodes, fileMap, filesToProcess)
141
138
  filesToProcess,
142
139
  };
143
140
  }
144
- async function updateProjectGraphWithPlugins(context, initProjectGraph) {
145
- const plugins = await (0, internal_api_1.loadNxPlugins)(context.nxJsonConfiguration?.plugins, context.workspaceRoot);
141
+ async function updateProjectGraphWithPlugins(context, initProjectGraph, plugins) {
146
142
  let graph = initProjectGraph;
147
143
  for (const plugin of plugins) {
148
144
  try {
@@ -1,6 +1,7 @@
1
1
  import { PluginConfiguration } from '../../config/nx-json';
2
2
  import { NxPluginV1 } from '../../utils/nx-plugin.deprecated';
3
3
  import { CreateNodesContext, CreateNodesResult, NxPluginV2 } from './public-api';
4
+ export { loadPlugins, loadPlugin } from './worker-api';
4
5
  export type CreateNodesResultWithContext = CreateNodesResult & {
5
6
  file: string;
6
7
  pluginName: string;
@@ -12,7 +13,10 @@ export type RemotePlugin = Omit<NormalizedPlugin, 'createNodes'> & {
12
13
  fn: (matchedFiles: string[], context: CreateNodesContext) => Promise<CreateNodesResultWithContext[]>
13
14
  ];
14
15
  };
15
- export declare const nxPluginCache: Map<unknown, Promise<RemotePlugin>>;
16
- export declare function loadNxPlugins(plugins: PluginConfiguration[], root?: string): Promise<RemotePlugin[]>;
17
- export declare function loadNxPlugin(plugin: PluginConfiguration, root?: string): Promise<RemotePlugin>;
16
+ export declare const nxPluginCache: Map<unknown, [Promise<RemotePlugin>, () => void]>;
17
+ /**
18
+ * This loads plugins in isolation in their own worker so that they do not disturb other workers or the main process.
19
+ */
20
+ export declare function loadNxPluginsInIsolation(plugins: PluginConfiguration[], root?: string): Promise<[RemotePlugin[], () => void]>;
21
+ export declare function loadNxPluginInIsolation(plugin: PluginConfiguration, root?: string): [Promise<RemotePlugin>, () => void];
18
22
  export declare function getDefaultPlugins(root: string): Promise<string[]>;
@@ -2,38 +2,54 @@
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.loadNxPlugin = exports.loadNxPlugins = exports.nxPluginCache = void 0;
5
+ exports.getDefaultPlugins = exports.loadNxPluginInIsolation = exports.loadNxPluginsInIsolation = exports.nxPluginCache = exports.loadPlugin = exports.loadPlugins = void 0;
6
6
  const path_1 = require("path");
7
7
  const workspace_root_1 = require("../../utils/workspace-root");
8
8
  const angular_json_1 = require("../../adapter/angular-json");
9
9
  const plugin_pool_1 = require("./plugin-pool");
10
+ var worker_api_1 = require("./worker-api");
11
+ Object.defineProperty(exports, "loadPlugins", { enumerable: true, get: function () { return worker_api_1.loadPlugins; } });
12
+ Object.defineProperty(exports, "loadPlugin", { enumerable: true, get: function () { return worker_api_1.loadPlugin; } });
10
13
  // Short lived cache (cleared between cmd runs)
11
14
  // holding resolved nx plugin objects.
12
15
  // Allows loaded plugins to not be reloaded when
13
16
  // referenced multiple times.
14
17
  exports.nxPluginCache = new Map();
15
- async function loadNxPlugins(plugins, root = workspace_root_1.workspaceRoot) {
18
+ /**
19
+ * This loads plugins in isolation in their own worker so that they do not disturb other workers or the main process.
20
+ */
21
+ async function loadNxPluginsInIsolation(plugins, root = workspace_root_1.workspaceRoot) {
16
22
  const result = [];
17
23
  plugins ??= [];
18
24
  plugins.unshift((0, path_1.join)(__dirname, '../../plugins/project-json/build-nodes/package-json-next-to-project-json'));
19
25
  // We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
20
26
  plugins.push(...(await getDefaultPlugins(root)));
27
+ const cleanupFunctions = [];
21
28
  for (const plugin of plugins) {
22
- result.push(loadNxPlugin(plugin, root));
29
+ const [loadedPluginPromise, cleanup] = loadNxPluginInIsolation(plugin, root);
30
+ result.push(loadedPluginPromise);
31
+ cleanupFunctions.push(cleanup);
23
32
  }
24
- return Promise.all(result);
33
+ return [
34
+ await Promise.all(result),
35
+ () => {
36
+ for (const fn of cleanupFunctions) {
37
+ fn();
38
+ }
39
+ },
40
+ ];
25
41
  }
26
- exports.loadNxPlugins = loadNxPlugins;
27
- async function loadNxPlugin(plugin, root = workspace_root_1.workspaceRoot) {
42
+ exports.loadNxPluginsInIsolation = loadNxPluginsInIsolation;
43
+ function loadNxPluginInIsolation(plugin, root = workspace_root_1.workspaceRoot) {
28
44
  const cacheKey = JSON.stringify(plugin);
29
45
  if (exports.nxPluginCache.has(cacheKey)) {
30
- return await exports.nxPluginCache.get(cacheKey);
46
+ return exports.nxPluginCache.get(cacheKey);
31
47
  }
32
- const loadingPlugin = (0, plugin_pool_1.loadRemoteNxPlugin)(plugin, root);
33
- exports.nxPluginCache.set(cacheKey, loadingPlugin);
34
- return await loadingPlugin;
48
+ const [loadingPlugin, cleanup] = (0, plugin_pool_1.loadRemoteNxPlugin)(plugin, root);
49
+ exports.nxPluginCache.set(cacheKey, [loadingPlugin, cleanup]);
50
+ return [loadingPlugin, cleanup];
35
51
  }
36
- exports.loadNxPlugin = loadNxPlugin;
52
+ exports.loadNxPluginInIsolation = loadNxPluginInIsolation;
37
53
  async function getDefaultPlugins(root) {
38
54
  return [
39
55
  (0, path_1.join)(__dirname, '../../plugins/js'),
@@ -1,4 +1,3 @@
1
1
  import { PluginConfiguration } from '../../config/nx-json';
2
2
  import { RemotePlugin } from './internal-api';
3
- export declare function loadRemoteNxPlugin(plugin: PluginConfiguration, root: string): Promise<RemotePlugin>;
4
- export declare function shutdownPluginWorkers(): Promise<void>;
3
+ export declare function loadRemoteNxPlugin(plugin: PluginConfiguration, root: string): readonly [Promise<RemotePlugin>, () => void];
@@ -1,17 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shutdownPluginWorkers = exports.loadRemoteNxPlugin = void 0;
3
+ exports.loadRemoteNxPlugin = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  const path = require("path");
6
6
  // TODO (@AgentEnder): After scoped verbose logging is implemented, re-add verbose logs here.
7
7
  // import { logger } from '../../utils/logger';
8
8
  const internal_api_1 = require("./internal-api");
9
9
  const messaging_1 = require("./messaging");
10
- const pool = new Set();
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();
10
+ const cleanupFunctions = new Set();
11
+ const pluginNames = new Map();
15
12
  function loadRemoteNxPlugin(plugin, root) {
16
13
  // this should only really be true when running unit tests within
17
14
  // the Nx repo. We still need to start the worker in this case,
@@ -36,40 +33,44 @@ function loadRemoteNxPlugin(plugin, root) {
36
33
  ],
37
34
  });
38
35
  worker.send((0, messaging_1.createMessage)({ type: 'load', payload: { plugin, root } }));
39
- pool.add(worker);
40
36
  // logger.verbose(`[plugin-worker] started worker: ${worker.pid}`);
41
- return new Promise((res, rej) => {
42
- worker.on('message', createWorkerHandler(worker, res, rej));
43
- worker.on('exit', createWorkerExitHandler(worker));
44
- });
37
+ const pendingPromises = new Map();
38
+ const exitHandler = createWorkerExitHandler(worker, pendingPromises);
39
+ const cleanupFunction = () => {
40
+ worker.off('exit', exitHandler);
41
+ shutdownPluginWorker(worker, pendingPromises);
42
+ };
43
+ cleanupFunctions.add(cleanupFunction);
44
+ return [
45
+ new Promise((res, rej) => {
46
+ worker.on('message', createWorkerHandler(worker, pendingPromises, res, rej));
47
+ worker.on('exit', exitHandler);
48
+ }),
49
+ () => {
50
+ cleanupFunction();
51
+ cleanupFunctions.delete(cleanupFunction);
52
+ },
53
+ ];
45
54
  }
46
55
  exports.loadRemoteNxPlugin = loadRemoteNxPlugin;
47
- let pluginWorkersShutdown = false;
48
- async function shutdownPluginWorkers() {
56
+ async function shutdownPluginWorker(worker, pendingPromises) {
49
57
  // Clears the plugin cache so no refs to the workers are held
50
58
  internal_api_1.nxPluginCache.clear();
51
- // Marks the workers as shutdown so that we don't report unexpected exits
52
- pluginWorkersShutdown = true;
53
59
  // logger.verbose(`[plugin-pool] starting worker shutdown`);
54
- const pending = getPendingPromises(pool, pidMap);
55
- for (const pendingPromise of pending) {
56
- pendingPromise.rejector(new Error('Shutting down'));
57
- }
58
- // logger.verbose(`[plugin-pool] all pending operations completed`);
59
- for (const childProcess of pool) {
60
- childProcess.kill('SIGINT');
61
- }
62
- // logger.verbose(`[plugin-pool] all workers killed`);
60
+ // Other things may be interacting with the worker.
61
+ // Wait for all pending promises to be done before killing the worker
62
+ await Promise.all(Array.from(pendingPromises.values()).map(({ promise }) => promise));
63
+ worker.kill('SIGINT');
63
64
  }
64
- exports.shutdownPluginWorkers = shutdownPluginWorkers;
65
65
  /**
66
66
  * Creates a message handler for the given worker.
67
67
  * @param worker Instance of plugin-worker
68
+ * @param pending Set of pending promises
68
69
  * @param onload Resolver for RemotePlugin promise
69
70
  * @param onloadError Rejecter for RemotePlugin promise
70
71
  * @returns Function to handle messages from the worker
71
72
  */
72
- function createWorkerHandler(worker, onload, onloadError) {
73
+ function createWorkerHandler(worker, pending, onload, onloadError) {
73
74
  let pluginName;
74
75
  return function (message) {
75
76
  const parsed = JSON.parse(message);
@@ -83,8 +84,7 @@ function createWorkerHandler(worker, onload, onloadError) {
83
84
  if (result.success) {
84
85
  const { name, createNodesPattern } = result;
85
86
  pluginName = name;
86
- const pending = new Set();
87
- pidMap.set(worker.pid, { name, pending });
87
+ pluginNames.set(worker, pluginName);
88
88
  onload({
89
89
  name,
90
90
  createNodes: createNodesPattern
@@ -130,81 +130,57 @@ function createWorkerHandler(worker, onload, onloadError) {
130
130
  }
131
131
  },
132
132
  createDependenciesResult: ({ tx, ...result }) => {
133
- const { resolver, rejector } = promiseBank.get(tx);
133
+ const { resolver, rejector } = pending.get(tx);
134
134
  if (result.success) {
135
135
  resolver(result.dependencies);
136
136
  }
137
137
  else if (result.success === false) {
138
138
  rejector(result.error);
139
139
  }
140
- pidMap.get(worker.pid)?.pending.delete(tx);
141
- promiseBank.delete(tx);
142
140
  },
143
141
  createNodesResult: ({ tx, ...result }) => {
144
- const { resolver, rejector } = promiseBank.get(tx);
142
+ const { resolver, rejector } = pending.get(tx);
145
143
  if (result.success) {
146
144
  resolver(result.result);
147
145
  }
148
146
  else if (result.success === false) {
149
147
  rejector(result.error);
150
148
  }
151
- pidMap.get(worker.pid)?.pending.delete(tx);
152
- promiseBank.delete(tx);
153
149
  },
154
150
  processProjectGraphResult: ({ tx, ...result }) => {
155
- const { resolver, rejector } = promiseBank.get(tx);
151
+ const { resolver, rejector } = pending.get(tx);
156
152
  if (result.success) {
157
153
  resolver(result.graph);
158
154
  }
159
155
  else if (result.success === false) {
160
156
  rejector(result.error);
161
157
  }
162
- pidMap.get(worker.pid)?.pending.delete(tx);
163
- promiseBank.delete(tx);
164
158
  },
165
159
  });
166
160
  };
167
161
  }
168
- function createWorkerExitHandler(worker) {
162
+ function createWorkerExitHandler(worker, pendingPromises) {
169
163
  return () => {
170
- if (!pluginWorkersShutdown) {
171
- pidMap.get(worker.pid)?.pending.forEach((tx) => {
172
- const { rejector } = promiseBank.get(tx);
173
- rejector(new Error(`Plugin worker ${pidMap.get(worker.pid).name ?? worker.pid} exited unexpectedly with code ${worker.exitCode}`));
174
- });
175
- shutdownPluginWorkers();
164
+ for (const [_, pendingPromise] of pendingPromises) {
165
+ pendingPromise.rejector(new Error(`Plugin worker ${pluginNames.get(worker) ?? worker.pid} exited unexpectedly with code ${worker.exitCode}`));
176
166
  }
177
167
  };
178
168
  }
179
169
  process.on('exit', () => {
180
- if (pool.size) {
181
- shutdownPluginWorkers();
170
+ for (const fn of cleanupFunctions) {
171
+ fn();
182
172
  }
183
173
  });
184
- function getPendingPromises(pool, pidMap) {
185
- const pendingTxs = [];
186
- for (const p of pool) {
187
- const { pending } = pidMap.get(p.pid) ?? { pending: new Set() };
188
- for (const tx of pending) {
189
- pendingTxs.push(promiseBank.get(tx));
190
- }
191
- }
192
- return pendingTxs;
193
- }
194
174
  function registerPendingPromise(tx, pending, callback) {
195
175
  let resolver, rejector;
196
176
  const promise = new Promise((res, rej) => {
197
177
  resolver = res;
198
178
  rejector = rej;
199
179
  callback();
200
- }).then((val) => {
201
- // Remove the promise from the pending set
180
+ }).finally(() => {
202
181
  pending.delete(tx);
203
- // Return the original value
204
- return val;
205
182
  });
206
- pending.add(tx);
207
- promiseBank.set(tx, {
183
+ pending.set(tx, {
208
184
  promise,
209
185
  resolver,
210
186
  rejector,
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const installation_directory_1 = require("../../utils/installation-directory");
4
- const worker_api_1 = require("./worker-api");
5
3
  const messaging_1 = require("./messaging");
6
- const retrieve_workspace_files_1 = require("../utils/retrieve-workspace-files");
7
4
  const utils_1 = require("./utils");
5
+ const worker_api_1 = require("./worker-api");
8
6
  global.NX_GRAPH_CREATION = true;
9
7
  let plugin;
10
8
  let pluginOptions;
@@ -13,7 +11,7 @@ process.on('message', async (message) => {
13
11
  load: async ({ plugin: pluginConfiguration, root }) => {
14
12
  process.chdir(root);
15
13
  try {
16
- ({ plugin, options: pluginOptions } = await loadPluginFromWorker(pluginConfiguration, root));
14
+ ({ plugin, options: pluginOptions } = await (0, worker_api_1.loadPlugin)(pluginConfiguration, root));
17
15
  return {
18
16
  type: 'load-result',
19
17
  payload: {
@@ -82,18 +80,6 @@ process.on('message', async (message) => {
82
80
  },
83
81
  });
84
82
  });
85
- let projectsWithoutInference;
86
- async function loadPluginFromWorker(plugin, root) {
87
- try {
88
- require.resolve(typeof plugin === 'string' ? plugin : plugin.plugin);
89
- }
90
- catch {
91
- // If a plugin cannot be resolved, we will need projects to resolve it
92
- projectsWithoutInference ??=
93
- await (0, retrieve_workspace_files_1.retrieveProjectConfigurationsWithoutPluginInference)(root);
94
- }
95
- return await (0, worker_api_1.loadNxPluginAsync)(plugin, (0, installation_directory_1.getNxRequirePaths)(root), projectsWithoutInference, root);
96
- }
97
83
  function runCreateNodesInParallel(configFiles, context) {
98
84
  const promises = configFiles.map((file) => {
99
85
  performance.mark(`${plugin.name}:createNodes:${file} - start`);