nx 23.1.0 → 23.2.0-beta.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 (60) hide show
  1. package/dist/src/ai/configure-ai-agents-disclaimer.d.ts +5 -0
  2. package/dist/src/ai/configure-ai-agents-disclaimer.js +31 -0
  3. package/dist/src/command-line/add/add.js +8 -1
  4. package/dist/src/command-line/import/import.js +1 -1
  5. package/dist/src/command-line/init/configure-plugins.js +3 -2
  6. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +4 -2
  7. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +4 -3
  8. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +4 -3
  9. package/dist/src/command-line/init/implementation/add-nx-to-turborepo.js +4 -3
  10. package/dist/src/command-line/init/implementation/angular/index.js +4 -2
  11. package/dist/src/command-line/init/implementation/utils.d.ts +3 -3
  12. package/dist/src/command-line/init/implementation/utils.js +22 -3
  13. package/dist/src/command-line/migrate/migrate.d.ts +13 -0
  14. package/dist/src/command-line/migrate/migrate.js +45 -0
  15. package/dist/src/command-line/release/utils/git.js +6 -2
  16. package/dist/src/command-line/show/show-target/info.js +11 -2
  17. package/dist/src/daemon/client/client.d.ts +0 -2
  18. package/dist/src/daemon/client/client.js +17 -19
  19. package/dist/src/devkit-internals.d.ts +2 -0
  20. package/dist/src/devkit-internals.js +7 -1
  21. package/dist/src/native/index.d.ts +1 -1
  22. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  23. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  24. package/dist/src/plugins/js/lock-file/npm-parser.js +71 -27
  25. package/dist/src/plugins/js/lock-file/pnpm-parser.js +46 -15
  26. package/dist/src/plugins/js/lock-file/project-graph-pruning.js +1 -1
  27. package/dist/src/plugins/js/lock-file/yarn-parser.js +32 -5
  28. package/dist/src/plugins/js/utils/register.d.ts +18 -0
  29. package/dist/src/plugins/js/utils/register.js +81 -0
  30. package/dist/src/plugins/js/utils/typescript.d.ts +9 -0
  31. package/dist/src/plugins/js/utils/typescript.js +15 -0
  32. package/dist/src/project-graph/error-types.js +41 -1
  33. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +4 -0
  34. package/dist/src/project-graph/plugins/transpiler.js +4 -0
  35. package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.d.ts +9 -12
  36. package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.js +77 -61
  37. package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.d.ts +1 -1
  38. package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.js +1 -1
  39. package/dist/src/project-graph/utils/project-configuration-utils.js +4 -6
  40. package/dist/src/tasks-runner/life-cycles/performance-analysis.d.ts +2 -0
  41. package/dist/src/tasks-runner/life-cycles/performance-analysis.js +15 -6
  42. package/dist/src/tasks-runner/life-cycles/performance-report.d.ts +2 -0
  43. package/dist/src/tasks-runner/life-cycles/performance-report.js +11 -2
  44. package/dist/src/tasks-runner/run-command.js +5 -3
  45. package/dist/src/utils/acknowledge-build-scripts.d.ts +13 -0
  46. package/dist/src/utils/acknowledge-build-scripts.js +100 -0
  47. package/dist/src/utils/catalog/manager-utils.d.ts +1 -2
  48. package/dist/src/utils/catalog/manager-utils.js +22 -5
  49. package/dist/src/utils/catalog/pnpm-manager.d.ts +1 -0
  50. package/dist/src/utils/catalog/pnpm-manager.js +3 -15
  51. package/dist/src/utils/catalog/yarn-manager.d.ts +1 -0
  52. package/dist/src/utils/catalog/yarn-manager.js +3 -15
  53. package/dist/src/utils/git-utils.d.ts +2 -3
  54. package/dist/src/utils/git-utils.js +101 -47
  55. package/dist/src/utils/min-release-age/behavior/pnpm.js +9 -7
  56. package/dist/src/utils/provenance.js +12 -2
  57. package/migrations.json +7 -1
  58. package/package.json +11 -11
  59. package/dist/src/migrations/update-17-3-0/nx-release-path.d.ts +0 -3
  60. package/dist/src/migrations/update-17-3-0/nx-release-path.js +0 -47
@@ -0,0 +1,5 @@
1
+ import { AgentStatusInfo } from '../daemon/message-types/configure-ai-agents';
2
+ /**
3
+ * Whether to show the "configure-ai-agents is outdated" banner after a task run.
4
+ */
5
+ export declare function shouldPrintConfigureAiAgentsDisclaimer(outdatedAgents: AgentStatusInfo[], workspaceRoot: string): boolean;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldPrintConfigureAiAgentsDisclaimer = shouldPrintConfigureAiAgentsDisclaimer;
4
+ const fs_1 = require("fs");
5
+ const detect_ai_agent_1 = require("./detect-ai-agent");
6
+ const constants_1 = require("./constants");
7
+ /**
8
+ * Whether to show the "configure-ai-agents is outdated" banner after a task run.
9
+ */
10
+ function shouldPrintConfigureAiAgentsDisclaimer(outdatedAgents, workspaceRoot) {
11
+ if (outdatedAgents.length === 0) {
12
+ return false;
13
+ }
14
+ const detectedAgent = (0, detect_ai_agent_1.detectAiAgent)();
15
+ if (detectedAgent) {
16
+ return outdatedAgents.some((agent) => agent.name === detectedAgent);
17
+ }
18
+ // Unsupported agents (e.g. qwen) cannot be configured via `nx configure-ai-agents`.
19
+ // If the repo already has Nx rules in AGENTS.md, skip the misleading warning.
20
+ const agentsMd = (0, constants_1.agentsMdPath)(workspaceRoot);
21
+ if (!(0, fs_1.existsSync)(agentsMd)) {
22
+ return true;
23
+ }
24
+ try {
25
+ const content = (0, fs_1.readFileSync)(agentsMd, 'utf-8');
26
+ return !constants_1.rulesRegex.test(content);
27
+ }
28
+ catch {
29
+ return true;
30
+ }
31
+ }
@@ -38,9 +38,16 @@ async function installPackage(pkgName, version, nxJson) {
38
38
  const pmv = (0, package_manager_1.getPackageManagerVersion)(pm);
39
39
  const pmc = (0, package_manager_1.getPackageManagerCommand)(pm);
40
40
  // if we explicitly specify latest in yarn berry, it won't resolve the version
41
- const command = pm === 'yarn' && (0, semver_1.gte)(pmv, '2.0.0') && version === 'latest'
41
+ let command = pm === 'yarn' && (0, semver_1.gte)(pmv, '2.0.0') && version === 'latest'
42
42
  ? `${pmc.addDev} ${pkgName}`
43
43
  : `${pmc.addDev} ${pkgName}@${version}`;
44
+ // pnpm 11+ fails the install when the plugin's own dependency tree
45
+ // carries unacknowledged build scripts, and the plugin's generators can
46
+ // only record allowBuilds decisions after this install. Warn and skip
47
+ // for this one install, like pnpm 10 did.
48
+ if (pm === 'pnpm' && (0, semver_1.gte)(pmv, '11.0.0')) {
49
+ command += ' --config.strictDepBuilds=false';
50
+ }
44
51
  await new Promise((resolve) => (0, child_process_1.exec)(command, {
45
52
  windowsHide: true,
46
53
  }, (error, stdout, stderr) => {
@@ -489,7 +489,7 @@ async function runInstallDestinationRepo(packageManager, destinationGitClient) {
489
489
  output_1.output.log({
490
490
  title: 'Installing dependencies for imported code',
491
491
  });
492
- (0, utils_1.runInstall)(workspace_root_1.workspaceRoot, (0, package_manager_1.getPackageManagerCommand)(packageManager));
492
+ (0, utils_1.runInstall)(workspace_root_1.workspaceRoot, packageManager, (0, package_manager_1.getPackageManagerCommand)(packageManager));
493
493
  await destinationGitClient.amendCommit();
494
494
  }
495
495
  catch (e) {
@@ -25,8 +25,9 @@ function installPluginPackages(repoRoot, pmc = (0, package_manager_1.getPackageM
25
25
  return;
26
26
  }
27
27
  if ((0, fs_1.existsSync)((0, path_1.join)(repoRoot, 'package.json'))) {
28
- (0, utils_1.addDepsToPackageJson)(repoRoot, plugins);
29
- (0, utils_1.runInstall)(repoRoot, pmc);
28
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
29
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager, plugins);
30
+ (0, utils_1.runInstall)(repoRoot, packageManager, pmc);
30
31
  }
31
32
  else {
32
33
  const nxJson = (0, configuration_1.readNxJson)(repoRoot);
@@ -7,6 +7,7 @@ const ignore = require("ignore");
7
7
  const path_1 = require("path");
8
8
  const fileutils_1 = require("../../../utils/fileutils");
9
9
  const output_1 = require("../../../utils/output");
10
+ const package_manager_1 = require("../../../utils/package-manager");
10
11
  const utils_1 = require("./utils");
11
12
  const connect_to_nx_cloud_1 = require("../../nx-cloud/connect/connect-to-nx-cloud");
12
13
  async function addNxToMonorepo(options, guided = true) {
@@ -76,9 +77,10 @@ async function addNxToMonorepo(options, guided = true) {
76
77
  }
77
78
  (0, utils_1.createNxJsonFile)(repoRoot, targetDefaults, cacheableOperations, scriptOutputs);
78
79
  (0, utils_1.updateGitIgnore)(repoRoot);
79
- (0, utils_1.addDepsToPackageJson)(repoRoot);
80
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
81
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager);
80
82
  output_1.output.log({ title: '📦 Installing dependencies' });
81
- (0, utils_1.runInstall)(repoRoot);
83
+ (0, utils_1.runInstall)(repoRoot, packageManager);
82
84
  if (nxCloudChoice === 'yes') {
83
85
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
84
86
  await (0, utils_1.initCloud)('nx-init-monorepo');
@@ -86,9 +86,10 @@ async function addNxToNest(options, packageJson) {
86
86
  : 'skip';
87
87
  }
88
88
  (0, utils_1.createNxJsonFile)(repoRoot, [], [...cacheableOperations, ...nestCacheableScripts], scriptOutputs);
89
- const pmc = (0, package_manager_1.getPackageManagerCommand)();
89
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
90
+ const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager);
90
91
  (0, utils_1.updateGitIgnore)(repoRoot);
91
- (0, utils_1.addDepsToPackageJson)(repoRoot);
92
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager);
92
93
  addNestPluginToPackageJson(repoRoot);
93
94
  (0, utils_1.markRootPackageJsonAsNxProjectLegacy)(repoRoot, cacheableOperations, pmc);
94
95
  createProjectJson(repoRoot, packageJson, nestCLIConfiguration);
@@ -98,7 +99,7 @@ async function addNxToNest(options, packageJson) {
98
99
  updateTsConfig(repoRoot, nestCLIConfiguration.sourceRoot);
99
100
  }
100
101
  output_1.output.log({ title: '📦 Installing dependencies' });
101
- (0, utils_1.runInstall)(repoRoot);
102
+ (0, utils_1.runInstall)(repoRoot, packageManager, pmc);
102
103
  if (nxCloudChoice === 'yes') {
103
104
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
104
105
  await (0, utils_1.initCloud)('nx-init-nest');
@@ -61,9 +61,10 @@ async function addNxToNpmRepo(options, guided = true) {
61
61
  : 'skip';
62
62
  }
63
63
  (0, utils_1.createNxJsonFile)(repoRoot, [], cacheableOperations, scriptOutputs);
64
- const pmc = (0, package_manager_1.getPackageManagerCommand)();
64
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
65
+ const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager);
65
66
  (0, utils_1.updateGitIgnore)(repoRoot);
66
- (0, utils_1.addDepsToPackageJson)(repoRoot);
67
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager);
67
68
  if (options.legacy) {
68
69
  (0, utils_1.markRootPackageJsonAsNxProjectLegacy)(repoRoot, cacheableOperations, pmc);
69
70
  }
@@ -71,7 +72,7 @@ async function addNxToNpmRepo(options, guided = true) {
71
72
  (0, utils_1.markPackageJsonAsNxProject)((0, path_1.join)(repoRoot, 'package.json'));
72
73
  }
73
74
  output_1.output.log({ title: '📦 Installing dependencies' });
74
- (0, utils_1.runInstall)(repoRoot, pmc);
75
+ (0, utils_1.runInstall)(repoRoot, packageManager, pmc);
75
76
  if (nxCloudChoice === 'yes') {
76
77
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
77
78
  await (0, utils_1.initCloud)('nx-init-npm-repo');
@@ -42,9 +42,10 @@ async function addNxToTurborepo(_options) {
42
42
  // Apply fallback JSON write
43
43
  (0, fileutils_1.writeJsonFile)(nxJsonPath, nxJson);
44
44
  }
45
- const pmc = (0, package_manager_1.getPackageManagerCommand)();
45
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
46
+ const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager);
46
47
  (0, utils_1.updateGitIgnore)(repoRoot);
47
- (0, utils_1.addDepsToPackageJson)(repoRoot);
48
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager);
48
49
  output_1.output.log({ title: '📦 Installing dependencies' });
49
- (0, utils_1.runInstall)(repoRoot, pmc);
50
+ (0, utils_1.runInstall)(repoRoot, packageManager, pmc);
50
51
  }
@@ -7,6 +7,7 @@ const fileutils_1 = require("../../../../utils/fileutils");
7
7
  const versions_1 = require("../../../../utils/versions");
8
8
  const object_sort_1 = require("../../../../utils/object-sort");
9
9
  const output_1 = require("../../../../utils/output");
10
+ const package_manager_1 = require("../../../../utils/package-manager");
10
11
  const package_json_1 = require("../../../../utils/package-json");
11
12
  const utils_1 = require("../utils");
12
13
  const integrated_workspace_1 = require("./integrated-workspace");
@@ -86,9 +87,10 @@ async function collectCacheableOperations(options) {
86
87
  return cacheableOperations;
87
88
  }
88
89
  function installDependencies() {
89
- (0, utils_1.addDepsToPackageJson)(repoRoot);
90
+ const packageManager = (0, package_manager_1.detectPackageManager)(repoRoot);
91
+ (0, utils_1.addDepsToPackageJson)(repoRoot, packageManager);
90
92
  addPluginDependencies();
91
- (0, utils_1.runInstall)(repoRoot);
93
+ (0, utils_1.runInstall)(repoRoot, packageManager);
92
94
  }
93
95
  function addPluginDependencies() {
94
96
  const packageJsonPath = (0, path_1.join)(repoRoot, 'package.json');
@@ -1,6 +1,6 @@
1
1
  import { NxJsonConfiguration, TargetDefaultEntry, TargetDefaults } from '../../../config/nx-json';
2
2
  import { PackageJson } from '../../../utils/package-json';
3
- import { PackageManagerCommands } from '../../../utils/package-manager';
3
+ import { PackageManager, PackageManagerCommands } from '../../../utils/package-manager';
4
4
  export declare function createNxJsonFile(repoRoot: string, topologicalTargets: string[], cacheableOperations: string[], scriptOutputs: {
5
5
  [name: string]: string;
6
6
  }): void;
@@ -13,9 +13,9 @@ export declare function createNxJsonFile(repoRoot: string, topologicalTargets: s
13
13
  */
14
14
  export declare function upsertTargetDefaultEntry(targetDefaults: TargetDefaults, target: string, patch: Partial<TargetDefaultEntry>): void;
15
15
  export declare function createNxJsonFromTurboJson(turboJson: Record<string, any>): NxJsonConfiguration;
16
- export declare function addDepsToPackageJson(repoRoot: string, additionalPackages?: string[]): void;
16
+ export declare function addDepsToPackageJson(repoRoot: string, packageManager: PackageManager, additionalPackages?: string[]): void;
17
17
  export declare function updateGitIgnore(root: string): void;
18
- export declare function runInstall(repoRoot: string, pmc?: PackageManagerCommands): void;
18
+ export declare function runInstall(repoRoot: string, packageManager?: PackageManager, pmc?: PackageManagerCommands): void;
19
19
  /**
20
20
  * Coerce any thrown value into a non-empty telemetry string. The naive
21
21
  * `error.message || String(error)` yields "" for bare `new Error()`.
@@ -18,9 +18,11 @@ exports.printFinalMessage = printFinalMessage;
18
18
  exports.isMonorepo = isMonorepo;
19
19
  const child_process_1 = require("child_process");
20
20
  const path_1 = require("path");
21
+ const semver_1 = require("semver");
21
22
  const fileutils_1 = require("../../../utils/fileutils");
22
23
  const output_1 = require("../../../utils/output");
23
24
  const package_manager_1 = require("../../../utils/package-manager");
25
+ const acknowledge_build_scripts_1 = require("../../../utils/acknowledge-build-scripts");
24
26
  const path_2 = require("../../../utils/path");
25
27
  const versions_1 = require("../../../utils/versions");
26
28
  const fs_1 = require("fs");
@@ -207,7 +209,7 @@ function createNxJsonFromTurboJson(turboJson) {
207
209
  }
208
210
  return nxJson;
209
211
  }
210
- function addDepsToPackageJson(repoRoot, additionalPackages) {
212
+ function addDepsToPackageJson(repoRoot, packageManager, additionalPackages) {
211
213
  const path = (0, path_2.joinPathFragments)(repoRoot, `package.json`);
212
214
  const json = (0, fileutils_1.readJsonFile)(path);
213
215
  if (!json.devDependencies)
@@ -219,6 +221,9 @@ function addDepsToPackageJson(repoRoot, additionalPackages) {
219
221
  }
220
222
  }
221
223
  (0, fileutils_1.writeJsonFile)(path, json);
224
+ // nx has a postinstall script, which pnpm 11+ refuses to install
225
+ // unacknowledged.
226
+ (0, acknowledge_build_scripts_1.acknowledgeBuildScripts)(repoRoot, packageManager, { nx: true });
222
227
  }
223
228
  function updateGitIgnore(root) {
224
229
  const ignorePath = (0, path_1.join)(root, '.gitignore');
@@ -251,9 +256,23 @@ function updateGitIgnore(root) {
251
256
  }
252
257
  catch { }
253
258
  }
254
- function runInstall(repoRoot, pmc = (0, package_manager_1.getPackageManagerCommand)()) {
259
+ function runInstall(repoRoot, packageManager = (0, package_manager_1.detectPackageManager)(repoRoot), pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager)) {
260
+ let command = pmc.install;
261
+ // Plugins added during init can pull build-script deps whose allowBuilds
262
+ // entries are only recorded by their init generators after this install;
263
+ // warn and skip for this one install, like pnpm 10 did.
264
+ if (packageManager === 'pnpm') {
265
+ try {
266
+ if ((0, semver_1.gte)((0, package_manager_1.getPackageManagerVersion)('pnpm', repoRoot), '11.0.0')) {
267
+ command += ' --config.strictDepBuilds=false';
268
+ }
269
+ }
270
+ catch {
271
+ // The version cannot be probed; run the install unmodified.
272
+ }
273
+ }
255
274
  try {
256
- (0, child_process_1.execSync)(pmc.install, {
275
+ (0, child_process_1.execSync)(command, {
257
276
  stdio: ['ignore', 'ignore', 'pipe'],
258
277
  encoding: 'utf8',
259
278
  cwd: repoRoot,
@@ -217,6 +217,19 @@ export declare function resolveCreateCommits(args: {
217
217
  warning?: string;
218
218
  error?: string;
219
219
  };
220
+ /**
221
+ * Confirms before creating per-migration commits while the user sits on the
222
+ * repository's default branch, so migrations don't silently commit there (most
223
+ * relevant since `--agentic` enables commits by default). Only the default
224
+ * branch triggers a prompt; a detached HEAD, a different branch, or an
225
+ * unresolved default branch all proceed untouched. Callers gate this on
226
+ * commits being effective and prompting being possible, so non-interactive
227
+ * runs (CI, `--no-interactive`) never reach here.
228
+ */
229
+ export declare function confirmCommitsOnDefaultBranch(args: {
230
+ currentBranch: string | null;
231
+ defaultBranch: string | null;
232
+ }): Promise<boolean>;
220
233
  /**
221
234
  * Resolves whether the framework-owned generic-validation agent step should run
222
235
  * after generator-only migrations.
@@ -11,6 +11,7 @@ exports.isNpmPeerDepsError = isNpmPeerDepsError;
11
11
  exports.resolveAgenticRunId = resolveAgenticRunId;
12
12
  exports.formatSkippedPromptsNextStep = formatSkippedPromptsNextStep;
13
13
  exports.resolveCreateCommits = resolveCreateCommits;
14
+ exports.confirmCommitsOnDefaultBranch = confirmCommitsOnDefaultBranch;
14
15
  exports.resolveShouldRunValidation = resolveShouldRunValidation;
15
16
  exports.executeMigrations = executeMigrations;
16
17
  exports.runNxOrAngularMigration = runNxOrAngularMigration;
@@ -39,6 +40,7 @@ const tar_1 = require("../../utils/tar");
39
40
  const write_formatted_json_file_1 = require("../../utils/write-formatted-json-file");
40
41
  const logger_1 = require("../../utils/logger");
41
42
  const git_utils_1 = require("../../utils/git-utils");
43
+ const command_line_utils_1 = require("../../utils/command-line-utils");
42
44
  const package_json_1 = require("../../utils/package-json");
43
45
  const package_manager_1 = require("../../utils/package-manager");
44
46
  const errors_1 = require("../../utils/min-release-age/errors");
@@ -1784,6 +1786,30 @@ function resolveCreateCommits(args) {
1784
1786
  : undefined,
1785
1787
  };
1786
1788
  }
1789
+ /**
1790
+ * Confirms before creating per-migration commits while the user sits on the
1791
+ * repository's default branch, so migrations don't silently commit there (most
1792
+ * relevant since `--agentic` enables commits by default). Only the default
1793
+ * branch triggers a prompt; a detached HEAD, a different branch, or an
1794
+ * unresolved default branch all proceed untouched. Callers gate this on
1795
+ * commits being effective and prompting being possible, so non-interactive
1796
+ * runs (CI, `--no-interactive`) never reach here.
1797
+ */
1798
+ async function confirmCommitsOnDefaultBranch(args) {
1799
+ const { currentBranch, defaultBranch } = args;
1800
+ if (!currentBranch || !defaultBranch || currentBranch !== defaultBranch) {
1801
+ return true;
1802
+ }
1803
+ const { proceed } = await (0, safe_prompt_1.migratePrompt)([
1804
+ {
1805
+ name: 'proceed',
1806
+ type: 'confirm',
1807
+ message: `You're on the default branch '${currentBranch}'. nx migrate will create a commit for each migration on this branch. Continue?`,
1808
+ initial: false,
1809
+ },
1810
+ ]);
1811
+ return proceed;
1812
+ }
1787
1813
  /**
1788
1814
  * Resolves whether the framework-owned generic-validation agent step should run
1789
1815
  * after generator-only migrations.
@@ -2304,6 +2330,25 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits, c
2304
2330
  if (createCommitsWarning) {
2305
2331
  output_1.output.warn({ title: createCommitsWarning });
2306
2332
  }
2333
+ if (effectiveCreateCommits && (0, safe_prompt_1.canPrompt)(opts.interactive)) {
2334
+ const currentBranch = (0, git_utils_1.getGitCurrentBranch)(root);
2335
+ // `getBaseRef` may carry an `origin/` prefix (set by the CI-workflow
2336
+ // generator); compare against the local branch name.
2337
+ const defaultBranch = (0, command_line_utils_1.getBaseRef)((0, configuration_1.readNxJson)(root)).replace(/^origin\//, '');
2338
+ const proceed = await confirmCommitsOnDefaultBranch({
2339
+ currentBranch,
2340
+ defaultBranch,
2341
+ });
2342
+ if (!proceed) {
2343
+ output_1.output.log({
2344
+ title: `Skipped running migrations to avoid committing to the default branch '${currentBranch}'.`,
2345
+ bodyLines: [
2346
+ 'Switch to a different branch and re-run, or re-run and confirm to proceed.',
2347
+ ],
2348
+ });
2349
+ return;
2350
+ }
2351
+ }
2307
2352
  const shouldRunValidation = resolveShouldRunValidation({
2308
2353
  validate: opts.validate,
2309
2354
  agenticKind: agentic.kind,
@@ -443,8 +443,10 @@ function extractReferencesFromCommit(commit) {
443
443
  references.push({ type: 'issue', value: m[1] });
444
444
  }
445
445
  }
446
- // Extract issue references from commit body
447
- for (const m of commit.body.matchAll(IssueRE)) {
446
+ // Extract issue references from commit body, only when linked via a closing
447
+ // keyword so that other repos' issue numbers mentioned in prose are not
448
+ // picked up (e.g. "web-infra-dev/rspack#2292")
449
+ for (const m of commit.body.matchAll(IssueClosingKeywordRE)) {
448
450
  if (!references.some((i) => i.value === m[1])) {
449
451
  references.push({ type: 'issue', value: m[1] });
450
452
  }
@@ -473,6 +475,8 @@ const PullRequestRE = /\([ a-z]*(#\d+)\s*\)/gm;
473
475
  // GitLab style merge request references
474
476
  const GitLabMergeRequestRE = /See merge request (?:[a-z0-9/-]+)?(![\d]+)/gim;
475
477
  const IssueRE = /(#\d+)/gm;
478
+ // GitHub style issue closing keywords, e.g. "Fixes #1234"
479
+ const IssueClosingKeywordRE = /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?):?\s+(#\d+)/gim;
476
480
  const ChangedFileRegex = /(A|M|D|R\d*|C\d*)\t([^\t\n]*)\t?(.*)?/gm;
477
481
  const RevertHashRE = /This reverts commit (?<hash>[\da-f]{40})./gm;
478
482
  function parseVersionPlanCommit(commit) {
@@ -116,8 +116,17 @@ function resolveDependencyProjects(dep, projectName, graph) {
116
116
  function resolveTaskGraphDependencies(graph, extraTargetDeps, projectName, targetName, configuration, depConfigs) {
117
117
  try {
118
118
  const taskGraph = (0, create_task_graph_1.createTaskGraph)(graph, extraTargetDeps, [projectName], [targetName], configuration, {});
119
- const rootId = (0, utils_1.createTaskId)(projectName, targetName, configuration);
120
- const directDeps = taskGraph.dependencies[rootId] ?? [];
119
+ // `createTaskGraph` resolves the target's `defaultConfiguration`, so the real
120
+ // root task id may carry a `:config` suffix that `createTaskId` with the raw
121
+ // configuration would omit. Find the root task by (project, target) instead.
122
+ const rootTask = Object.values(taskGraph.tasks).find((task) => task.target.project === projectName && task.target.target === targetName);
123
+ const rootId = rootTask?.id ?? (0, utils_1.createTaskId)(projectName, targetName, configuration);
124
+ // Continuous dependencies (e.g. dev servers) live in a separate map but are
125
+ // direct dependencies just like the entries in `dependencies`.
126
+ const directDeps = [
127
+ ...(taskGraph.dependencies[rootId] ?? []),
128
+ ...(taskGraph.continuousDependencies[rootId] ?? []),
129
+ ];
121
130
  const directDepSet = new Set(directDeps);
122
131
  const depSourceIndices = directDeps.map((depTaskId) => {
123
132
  const task = taskGraph.tasks[depTaskId];
@@ -26,8 +26,6 @@ export declare class DaemonClient {
26
26
  private _daemonStatus;
27
27
  private _waitForDaemonReady;
28
28
  private _daemonReady;
29
- private _out;
30
- private _err;
31
29
  private fileWatcherMessenger;
32
30
  private fileWatcherReconnecting;
33
31
  private fileWatcherCallbacks;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.daemonClient = exports.DaemonClient = void 0;
4
4
  exports.isDaemonEnabled = isDaemonEnabled;
5
5
  const child_process_1 = require("child_process");
6
- const promises_1 = require("fs/promises");
7
6
  const net_1 = require("net");
8
7
  const node_fs_1 = require("node:fs");
9
8
  const path_1 = require("path");
@@ -12,6 +11,7 @@ const configuration_1 = require("../../config/configuration");
12
11
  const nx_json_1 = require("../../config/nx-json");
13
12
  const native_1 = require("../../native");
14
13
  const error_types_1 = require("../../project-graph/error-types");
14
+ const typescript_1 = require("../../plugins/js/utils/typescript");
15
15
  const project_graph_1 = require("../../project-graph/project-graph");
16
16
  const consume_messages_from_socket_1 = require("../../utils/consume-messages-from-socket");
17
17
  const delayed_spinner_1 = require("../../utils/delayed-spinner");
@@ -62,8 +62,6 @@ class DaemonClient {
62
62
  this._daemonStatus = DaemonStatus.DISCONNECTED;
63
63
  this._waitForDaemonReady = null;
64
64
  this._daemonReady = null;
65
- this._out = null;
66
- this._err = null;
67
65
  this.fileWatcherReconnecting = false;
68
66
  this.fileWatcherCallbacks = new Map();
69
67
  this.fileWatcherConfigs = new Map();
@@ -127,10 +125,6 @@ class DaemonClient {
127
125
  this.currentResolve = null;
128
126
  this.currentReject = null;
129
127
  this._enabled = undefined;
130
- this._out?.close();
131
- this._err?.close();
132
- this._out = null;
133
- this._err = null;
134
128
  // Clean up file watcher and project graph listener connections
135
129
  this.fileWatcherMessenger?.close();
136
130
  this.fileWatcherMessenger = undefined;
@@ -949,25 +943,29 @@ class DaemonClient {
949
943
  if (!(0, node_fs_1.existsSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE)) {
950
944
  (0, node_fs_1.writeFileSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, '');
951
945
  }
952
- // Open the log handles into locals first. If the previous daemon's
953
- // socket close handler fires reset() while we're awaiting these opens,
954
- // it would null out this._out/this._err and the spawn below would hit
955
- // `Cannot read properties of null (reading 'fd')`.
956
- const [out, err] = await Promise.all([
957
- (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a'),
958
- (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a'),
959
- ]);
960
- this._out = out;
961
- this._err = err;
946
+ // Redirect the detached daemon's stdout/stderr into the log file. The
947
+ // child dup's these descriptors at spawn, so we close ours right after
948
+ // instead of holding them for the life of this process (Node >=26 turns a
949
+ // file descriptor closed during garbage collection into a fatal error).
950
+ const outFd = (0, node_fs_1.openSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a');
951
+ const errFd = (0, node_fs_1.openSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a');
962
952
  logger_1.clientLogger.log(`[Client] Starting new daemon server in background`);
963
- const backgroundProcess = (0, child_process_1.spawn)(process.execPath, [(0, path_1.join)(__dirname, `../server/start.js`)], {
953
+ const backgroundProcess = (0, child_process_1.spawn)(process.execPath, [
954
+ // Spawn with the same resolve conditions Nx uses for plugin entries so a
955
+ // source-loaded plugin's transitive workspace imports resolve to source.
956
+ ...(0, typescript_1.getPluginResolveConditionNodeArgs)(),
957
+ (0, path_1.join)(__dirname, `../server/start.js`),
958
+ ], {
964
959
  cwd: workspace_root_1.workspaceRoot,
965
- stdio: ['ignore', out.fd, err.fd],
960
+ stdio: ['ignore', outFd, errFd],
966
961
  detached: true,
967
962
  windowsHide: true,
968
963
  shell: false,
969
964
  env: (0, daemon_environment_1.getDaemonEnv)(),
970
965
  });
966
+ // The child now owns dup'd copies of the descriptors, so release ours.
967
+ (0, node_fs_1.closeSync)(outFd);
968
+ (0, node_fs_1.closeSync)(errFd);
971
969
  // if this process is the process that spawned the daemon,
972
970
  // the daemon env is already up to date
973
971
  this.envReflectionSent = true;
@@ -38,3 +38,5 @@ export { PluginCache, safeWriteFileCache } from './utils/plugin-cache-utils';
38
38
  export { emitPluginWorkerLog } from './project-graph/plugins/isolation/worker-streaming';
39
39
  export { resolveImplementation, resolveSchema, ImplementationResolutionError, SchemaResolutionError, } from './config/schema-utils';
40
40
  export { resolvePrompt, PromptResolutionError, } from './command-line/migrate/prompt-files';
41
+ export { getCatalogManager, getCatalogDependenciesFromPackageJson, } from './utils/catalog';
42
+ export { acknowledgeBuildScripts } from './utils/acknowledge-build-scripts';
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PromptResolutionError = exports.resolvePrompt = exports.SchemaResolutionError = exports.ImplementationResolutionError = exports.resolveSchema = exports.resolveImplementation = exports.emitPluginWorkerLog = exports.safeWriteFileCache = exports.PluginCache = exports.handleImport = exports.signalToCode = exports.globalSpinner = exports.readYamlFile = exports.isUsingPrettierInTree = exports.isCI = exports.interpolate = exports.requireWithTsconfigFallback = exports.forceRegisterEsmLoader = exports.loadTsFile = exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappings = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashMultiGlobWithWorkspaceContext = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.installPackageToTmpAsync = exports.installPackageToTmp = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.getIgnoreObjectForTree = exports.readTargetDefaultsForTarget = exports.findMatchingProjects = exports.findMatchingConfigFiles = exports.readProjectConfigurationsFromRootMap = exports.mergeTargetConfigurations = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.parseExecutor = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
3
+ exports.getCatalogDependenciesFromPackageJson = exports.getCatalogManager = exports.PromptResolutionError = exports.resolvePrompt = exports.SchemaResolutionError = exports.ImplementationResolutionError = exports.resolveSchema = exports.resolveImplementation = exports.emitPluginWorkerLog = exports.safeWriteFileCache = exports.PluginCache = exports.handleImport = exports.signalToCode = exports.globalSpinner = exports.readYamlFile = exports.isUsingPrettierInTree = exports.isCI = exports.interpolate = exports.requireWithTsconfigFallback = exports.forceRegisterEsmLoader = exports.loadTsFile = exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappings = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashMultiGlobWithWorkspaceContext = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.installPackageToTmpAsync = exports.installPackageToTmp = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.getIgnoreObjectForTree = exports.readTargetDefaultsForTarget = exports.findMatchingProjects = exports.findMatchingConfigFiles = exports.readProjectConfigurationsFromRootMap = exports.mergeTargetConfigurations = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.parseExecutor = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
4
+ exports.acknowledgeBuildScripts = void 0;
4
5
  const tslib_1 = require("tslib");
5
6
  /**
6
7
  * Note to developers: STOP! These exports are available via requireNx in @nx/devkit.
@@ -90,3 +91,8 @@ Object.defineProperty(exports, "SchemaResolutionError", { enumerable: true, get:
90
91
  var prompt_files_1 = require("./command-line/migrate/prompt-files");
91
92
  Object.defineProperty(exports, "resolvePrompt", { enumerable: true, get: function () { return prompt_files_1.resolvePrompt; } });
92
93
  Object.defineProperty(exports, "PromptResolutionError", { enumerable: true, get: function () { return prompt_files_1.PromptResolutionError; } });
94
+ var catalog_1 = require("./utils/catalog");
95
+ Object.defineProperty(exports, "getCatalogManager", { enumerable: true, get: function () { return catalog_1.getCatalogManager; } });
96
+ Object.defineProperty(exports, "getCatalogDependenciesFromPackageJson", { enumerable: true, get: function () { return catalog_1.getCatalogDependenciesFromPackageJson; } });
97
+ var acknowledge_build_scripts_1 = require("./utils/acknowledge-build-scripts");
98
+ Object.defineProperty(exports, "acknowledgeBuildScripts", { enumerable: true, get: function () { return acknowledge_build_scripts_1.acknowledgeBuildScripts; } });
@@ -28,7 +28,7 @@ export declare class ExternalObject<T> {
28
28
  }
29
29
  }
30
30
  export declare class AppLifeCycle {
31
- constructor(tasks: Array<Task>, initiatingTasks: Array<string>, runMode: RunMode, pinnedTasks: Array<string>, tuiCliArgs: TuiCliArgs, tuiConfig: TuiConfig, titleText: string, workspaceRoot: string, taskGraph: TaskGraph)
31
+ constructor(tasks: Array<Task>, initiatingTasks: Array<string>, runMode: RunMode, pinnedTasks: Array<string>, tuiCliArgs: TuiCliArgs, tuiConfig: TuiConfig, titleText: string, workspaceRoot: string, taskGraph: TaskGraph, isCloudEnabled?: boolean | undefined | null)
32
32
  startCommand(threadCount?: number | undefined | null): void
33
33
  scheduleTask(task: Task): void
34
34
  startTasks(tasks: Array<Task>, metadata: object): void
Binary file