nx 23.2.0-beta.7 → 23.2.0-beta.8

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 (130) hide show
  1. package/dist/bin/init-local.js +3 -5
  2. package/dist/release/changelog-renderer/index.js +4 -5
  3. package/dist/src/adapter/ngcli-adapter.js +60 -1
  4. package/dist/src/command-line/completion/command-object.js +7 -12
  5. package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +17 -23
  6. package/dist/src/command-line/generate/generate.js +35 -35
  7. package/dist/src/command-line/import/import.js +18 -40
  8. package/dist/src/command-line/init/ai-agent-prompts.js +5 -11
  9. package/dist/src/command-line/init/command-object.js +4 -2
  10. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +12 -32
  11. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +8 -21
  12. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +8 -21
  13. package/dist/src/command-line/init/implementation/angular/index.js +6 -15
  14. package/dist/src/command-line/init/init-v1.js +8 -18
  15. package/dist/src/command-line/init/init-v2.js +26 -56
  16. package/dist/src/command-line/migrate/agentic/definitions.js +35 -8
  17. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +22 -3
  18. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +13 -10
  19. package/dist/src/command-line/migrate/agentic/handoff.d.ts +3 -1
  20. package/dist/src/command-line/migrate/agentic/handoff.js +4 -2
  21. package/dist/src/command-line/migrate/agentic/run-step.js +1 -0
  22. package/dist/src/command-line/migrate/agentic/runner.js +24 -24
  23. package/dist/src/command-line/migrate/agentic/select.js +20 -30
  24. package/dist/src/command-line/migrate/agentic/types.d.ts +19 -3
  25. package/dist/src/command-line/migrate/agentic/types.js +13 -4
  26. package/dist/src/command-line/migrate/command-object.d.ts +3 -0
  27. package/dist/src/command-line/migrate/command-object.js +13 -0
  28. package/dist/src/command-line/migrate/execute-migration.d.ts +14 -0
  29. package/dist/src/command-line/migrate/execute-migration.js +30 -9
  30. package/dist/src/command-line/migrate/migrate-analytics.d.ts +28 -0
  31. package/dist/src/command-line/migrate/migrate-analytics.js +51 -1
  32. package/dist/src/command-line/migrate/migrate-commits.d.ts +8 -2
  33. package/dist/src/command-line/migrate/migrate-commits.js +66 -19
  34. package/dist/src/command-line/migrate/migrate-config.d.ts +4 -2
  35. package/dist/src/command-line/migrate/migrate-config.js +12 -4
  36. package/dist/src/command-line/migrate/migrate.d.ts +9 -2
  37. package/dist/src/command-line/migrate/migrate.js +179 -56
  38. package/dist/src/command-line/migrate/multi-major.js +7 -10
  39. package/dist/src/command-line/migrate/resolve-package-version.js +4 -8
  40. package/dist/src/command-line/migrate/run/agent-output.d.ts +20 -0
  41. package/dist/src/command-line/migrate/run/agent-output.js +65 -0
  42. package/dist/src/command-line/migrate/run/index.d.ts +7 -0
  43. package/dist/src/command-line/migrate/run/index.js +19 -1
  44. package/dist/src/command-line/migrate/run/orchestrator.d.ts +20 -0
  45. package/dist/src/command-line/migrate/run/orchestrator.js +1200 -0
  46. package/dist/src/command-line/migrate/run/run-id.d.ts +16 -0
  47. package/dist/src/command-line/migrate/run/run-id.js +56 -0
  48. package/dist/src/command-line/migrate/run/run-state.d.ts +157 -0
  49. package/dist/src/command-line/migrate/run/run-state.js +438 -0
  50. package/dist/src/command-line/migrate/run/state-lock.d.ts +25 -0
  51. package/dist/src/command-line/migrate/run/state-lock.js +76 -0
  52. package/dist/src/command-line/migrate/run/state-machine.d.ts +84 -0
  53. package/dist/src/command-line/migrate/run/state-machine.js +315 -0
  54. package/dist/src/command-line/migrate/run/util.d.ts +58 -0
  55. package/dist/src/command-line/migrate/run/util.js +139 -7
  56. package/dist/src/command-line/migrate/run/worker.d.ts +1 -0
  57. package/dist/src/command-line/migrate/run/worker.js +308 -45
  58. package/dist/src/command-line/migrate/safe-prompt.d.ts +14 -26
  59. package/dist/src/command-line/migrate/safe-prompt.js +32 -43
  60. package/dist/src/command-line/migrate/step-actions.d.ts +5 -0
  61. package/dist/src/command-line/migrate/step-actions.js +12 -0
  62. package/dist/src/command-line/migrate/text.d.ts +18 -0
  63. package/dist/src/command-line/migrate/text.js +26 -0
  64. package/dist/src/command-line/migrate/version-skew-guard.d.ts +6 -4
  65. package/dist/src/command-line/migrate/version-skew-guard.js +34 -14
  66. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +16 -20
  67. package/dist/src/command-line/release/changelog.js +6 -17
  68. package/dist/src/command-line/release/plan.js +15 -28
  69. package/dist/src/command-line/release/release.js +6 -17
  70. package/dist/src/command-line/release/utils/remote-release-clients/github.js +16 -22
  71. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +13 -22
  72. package/dist/src/command-line/release/utils/resolve-semver-specifier.js +19 -41
  73. package/dist/src/command-line/release/version/resolve-current-version.js +7 -10
  74. package/dist/src/core/graph/main.js +1 -1
  75. package/dist/src/devkit-internals.d.ts +2 -0
  76. package/dist/src/devkit-internals.js +12 -4
  77. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.d.ts +12 -0
  78. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.js +250 -0
  79. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md +50 -0
  80. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  81. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  82. package/dist/src/plugins/js/lock-file/bun-parser.js +43 -10
  83. package/dist/src/project-graph/utils/project-configuration/target-normalization.js +128 -2
  84. package/dist/src/tasks-runner/run-command.js +17 -32
  85. package/dist/src/tasks-runner/task-env.js +5 -2
  86. package/dist/src/tasks-runner/utils.js +2 -6
  87. package/dist/src/utils/analytics-prompt.js +4 -7
  88. package/dist/src/utils/exit-codes.d.ts +9 -0
  89. package/dist/src/utils/exit-codes.js +19 -0
  90. package/dist/src/utils/fileutils.d.ts +5 -0
  91. package/dist/src/utils/fileutils.js +7 -2
  92. package/dist/src/utils/git-utils.d.ts +33 -2
  93. package/dist/src/utils/git-utils.js +156 -8
  94. package/dist/src/utils/long-running-target.d.ts +10 -0
  95. package/dist/src/utils/long-running-target.js +19 -0
  96. package/dist/src/utils/min-release-age/behavior/bun.js +7 -11
  97. package/dist/src/utils/min-release-age/behavior/npm.js +5 -2
  98. package/dist/src/utils/min-release-age/packument.js +1 -1
  99. package/dist/src/utils/nx-console-prompt.js +3 -6
  100. package/dist/src/utils/package-manager-config/bunfig.d.ts +14 -0
  101. package/dist/src/utils/package-manager-config/bunfig.js +49 -0
  102. package/dist/src/utils/package-manager-config/npmrc.d.ts +23 -0
  103. package/dist/src/utils/package-manager-config/npmrc.js +124 -0
  104. package/dist/src/utils/package-manager-config/pnpm-config.d.ts +17 -0
  105. package/dist/src/utils/package-manager-config/pnpm-config.js +60 -0
  106. package/dist/src/utils/package-manager.d.ts +21 -2
  107. package/dist/src/utils/package-manager.js +244 -47
  108. package/dist/src/utils/params.d.ts +7 -1
  109. package/dist/src/utils/params.js +64 -6
  110. package/dist/src/utils/prompt-helpers.d.ts +53 -0
  111. package/dist/src/utils/prompt-helpers.js +111 -0
  112. package/dist/src/utils/provenance.js +6 -14
  113. package/dist/src/utils/registry-config/bun.d.ts +2 -0
  114. package/dist/src/utils/registry-config/bun.js +257 -0
  115. package/dist/src/utils/registry-config/index.d.ts +13 -0
  116. package/dist/src/utils/registry-config/index.js +102 -0
  117. package/dist/src/utils/registry-config/pnpm.d.ts +2 -0
  118. package/dist/src/utils/registry-config/pnpm.js +1551 -0
  119. package/dist/src/utils/registry-config/utils.d.ts +195 -0
  120. package/dist/src/utils/registry-config/utils.js +496 -0
  121. package/dist/src/utils/registry-config/yarn-berry.d.ts +2 -0
  122. package/dist/src/utils/registry-config/yarn-berry.js +612 -0
  123. package/dist/src/utils/registry-config/yarn-classic.d.ts +2 -0
  124. package/dist/src/utils/registry-config/yarn-classic.js +1001 -0
  125. package/dist/src/utils/safe-spawn.d.ts +24 -0
  126. package/dist/src/utils/safe-spawn.js +104 -0
  127. package/migrations.json +6 -0
  128. package/package.json +17 -13
  129. package/dist/src/utils/min-release-age/npmrc.d.ts +0 -15
  130. package/dist/src/utils/min-release-age/npmrc.js +0 -45
@@ -6,7 +6,7 @@ const perf_hooks_1 = require("perf_hooks");
6
6
  const nx_commands_1 = require("../src/command-line/nx-commands");
7
7
  const strip_indents_1 = require("../src/utils/strip-indents");
8
8
  const client_1 = require("../src/daemon/client/client");
9
- const enquirer_1 = require("enquirer");
9
+ const prompt_helpers_1 = require("../src/utils/prompt-helpers");
10
10
  const output_1 = require("../src/utils/output");
11
11
  const analytics_1 = require("../src/analytics");
12
12
  /**
@@ -136,11 +136,9 @@ async function ensureNxConsoleInstalledViaDaemon() {
136
136
  ],
137
137
  });
138
138
  try {
139
- const { shouldInstallNxConsole } = await (0, enquirer_1.prompt)({
140
- type: 'confirm',
141
- name: 'shouldInstallNxConsole',
139
+ const shouldInstallNxConsole = await (0, prompt_helpers_1.confirmationPrompt)({
142
140
  message: 'Install Nx Console? (you can uninstall anytime)',
143
- initial: true,
141
+ onCancel: () => false,
144
142
  });
145
143
  // Set preference and install if user said yes
146
144
  const result = await client_1.daemonClient.setNxConsolePreferenceAndInstall(shouldInstallNxConsole);
@@ -215,12 +215,11 @@ class DefaultChangelogRenderer {
215
215
  if (!name || name.includes('[bot]')) {
216
216
  continue;
217
217
  }
218
- if (_authors.has(name)) {
219
- const entry = _authors.get(name);
220
- entry.email.add(author.email);
218
+ if (!_authors.has(name)) {
219
+ _authors.set(name, { email: new Set() });
221
220
  }
222
- else {
223
- _authors.set(name, { email: new Set([author.email]) });
221
+ if (author.email) {
222
+ _authors.get(name).email.add(author.email);
224
223
  }
225
224
  }
226
225
  }
@@ -31,6 +31,7 @@ const executor_utils_1 = require("../command-line/run/executor-utils");
31
31
  const plugins_1 = require("../project-graph/plugins");
32
32
  const schema_utils_1 = require("../config/schema-utils");
33
33
  const handle_import_1 = require("../utils/handle-import");
34
+ const prompt_helpers_1 = require("../utils/prompt-helpers");
34
35
  const target_merging_1 = require("../project-graph/utils/project-configuration/target-merging");
35
36
  function getProjectGraph() {
36
37
  try {
@@ -653,8 +654,66 @@ function createPromptProvider() {
653
654
  return { ...question, type: definition.type };
654
655
  }
655
656
  });
656
- return require('enquirer').prompt(questions);
657
+ // Angular hands over a whole form at once; clack asks one question at a
658
+ // time, so they are run in order and the answers reassembled.
659
+ return (async () => {
660
+ const answers = {};
661
+ for (const question of questions) {
662
+ answers[question.name] = await askSchematicQuestion(question);
663
+ }
664
+ return answers;
665
+ })();
657
666
  };
667
+ async function askSchematicQuestion(question) {
668
+ const validate = question.validate
669
+ ? (value) => {
670
+ const result = question.validate(value);
671
+ if (result === true)
672
+ return undefined;
673
+ return typeof result === 'string' ? result : 'Invalid value';
674
+ }
675
+ : undefined;
676
+ const choices = (question.choices ?? []).map((c) => typeof c === 'string' ? { value: c } : { value: c.name, label: c.message });
677
+ switch (question.type) {
678
+ case 'confirm':
679
+ return (0, prompt_helpers_1.confirmationPrompt)({
680
+ message: question.message,
681
+ initial: question.initial !== false,
682
+ });
683
+ case 'select':
684
+ return (0, prompt_helpers_1.selectPrompt)({
685
+ message: question.message,
686
+ choices,
687
+ initial: question.initial,
688
+ });
689
+ case 'multiselect':
690
+ return (0, prompt_helpers_1.multiselectPrompt)({
691
+ message: question.message,
692
+ choices,
693
+ initialValues: question.initial,
694
+ });
695
+ case 'numeral': {
696
+ // No numeric prompt; the answer is parsed back so callers still get a
697
+ // number rather than the typed string.
698
+ const answer = await (0, prompt_helpers_1.textPrompt)({
699
+ message: question.message,
700
+ initialValue: question.initial === undefined
701
+ ? undefined
702
+ : String(question.initial),
703
+ validate: (value) => value !== '' && !Number.isNaN(Number(value))
704
+ ? validate?.(value)
705
+ : 'Please enter a number',
706
+ });
707
+ return Number(answer);
708
+ }
709
+ default:
710
+ return (0, prompt_helpers_1.textPrompt)({
711
+ message: question.message,
712
+ initialValue: question.initial,
713
+ validate,
714
+ });
715
+ }
716
+ }
658
717
  }
659
718
  async function runMigration(root, packageName, migrationName, projects, isVerbose, projectGraph) {
660
719
  const logger = (0, exports.getLogger)(isVerbose);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.yargsCompletionCommand = void 0;
4
- const enquirer_1 = require("enquirer");
4
+ const prompt_helpers_1 = require("../../utils/prompt-helpers");
5
5
  const fs_1 = require("fs");
6
6
  const os_1 = require("os");
7
7
  const path_1 = require("path");
@@ -69,18 +69,13 @@ async function pickShellsInteractively() {
69
69
  process.exit(1);
70
70
  }
71
71
  const detected = detectAvailableShells();
72
- const answer = (await (0, enquirer_1.prompt)({
73
- type: 'multiselect',
74
- name: 'shells',
72
+ return await (0, prompt_helpers_1.multiselectPrompt)({
75
73
  message: 'Install nx completion for which shell(s)?',
76
- choices: SHELL_CHOICES.map((name) => ({
77
- name,
78
- value: name,
79
- // Pre-check shells we can detect on this machine.
80
- enabled: detected.has(name),
81
- })),
82
- }));
83
- return answer.shells ?? [];
74
+ choices: SHELL_CHOICES,
75
+ // Pre-select shells we can detect on this machine.
76
+ initialValues: SHELL_CHOICES.filter((name) => detected.has(name)),
77
+ onCancel: () => [],
78
+ });
84
79
  }
85
80
  /** Best-effort detect-which-shells-the-user-has. Pre-checks the multiselect.
86
81
  * Signals: $SHELL basename, presence of conventional rc files, $PSModulePath
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.configureAiAgentsHandler = configureAiAgentsHandler;
4
4
  exports.configureAiAgentsHandlerImpl = configureAiAgentsHandlerImpl;
5
5
  const tslib_1 = require("tslib");
6
- const enquirer_1 = require("enquirer");
6
+ const prompt_helpers_1 = require("../../utils/prompt-helpers");
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = require("node:path");
9
9
  const pc = tslib_1.__importStar(require("picocolors"));
@@ -63,8 +63,10 @@ async function configureAiAgentsHandler(args, inner = false) {
63
63
  await resetDaemonAgentStatus();
64
64
  }
65
65
  async function configureAiAgentsHandlerImpl(options) {
66
- // Node 24 has stricter readline behavior, and enquirer is not checking for closed state
67
- // when invoking operations, thus you get an ERR_USE_AFTER_CLOSE error.
66
+ // Node 24's stricter readline throws ERR_USE_AFTER_CLOSE when a prompt
67
+ // library operates on a closed interface. Added for enquirer, which nx no
68
+ // longer uses; verify against Node 24 before removing.
69
+ // TODO(v24): drop if @clack/prompts proves not to need it.
68
70
  process.on('uncaughtException', (error) => {
69
71
  if (error &&
70
72
  typeof error === 'object' &&
@@ -158,7 +160,7 @@ async function configureAiAgentsHandlerImpl(options) {
158
160
  ...partiallyConfiguredAgents,
159
161
  ...outOfDateAgents,
160
162
  ...nonConfiguredAgents,
161
- ].map((a) => getAgentChoiceForPrompt(a).message),
163
+ ].map((a) => getAgentChoiceForPrompt(a).label),
162
164
  });
163
165
  process.exit(1);
164
166
  }
@@ -239,26 +241,22 @@ async function configureAiAgentsHandlerImpl(options) {
239
241
  }
240
242
  // Interactive mode (or non-interactive with explicit --agents)
241
243
  const allAgentChoices = [];
242
- const preselectedIndices = [];
243
- let currentIndex = 0;
244
+ const preselectedAgents = [];
244
245
  // Partially configured agents first (highest priority)
245
246
  partiallyConfiguredAgents.forEach((a) => {
246
247
  allAgentChoices.push(getAgentChoiceForPrompt(a));
247
- preselectedIndices.push(currentIndex);
248
- currentIndex++;
248
+ preselectedAgents.push(a.name);
249
249
  });
250
250
  // Outdated agents second
251
251
  for (const a of fullyConfiguredAgents) {
252
252
  if (a.outdated) {
253
253
  allAgentChoices.push(getAgentChoiceForPrompt(a));
254
- preselectedIndices.push(currentIndex);
255
- currentIndex++;
254
+ preselectedAgents.push(a.name);
256
255
  }
257
256
  }
258
257
  // Non-configured agents last
259
258
  nonConfiguredAgents.forEach((a) => {
260
259
  allAgentChoices.push(getAgentChoiceForPrompt(a));
261
- currentIndex++;
262
260
  });
263
261
  if (allAgentChoices.length === 0) {
264
262
  output_1.output.success({
@@ -270,18 +268,13 @@ async function configureAiAgentsHandlerImpl(options) {
270
268
  let selectedAgents;
271
269
  if (options.interactive !== false) {
272
270
  try {
273
- selectedAgents = (await (0, enquirer_1.prompt)({
274
- type: 'multiselect',
275
- name: 'agents',
271
+ selectedAgents = await (0, prompt_helpers_1.multiselectPrompt)({
276
272
  message: 'Which AI agents would you like to configure? (space to select, enter to confirm)',
277
273
  choices: allAgentChoices,
278
- initial: preselectedIndices,
274
+ initialValues: preselectedAgents,
279
275
  required: true,
280
- footer: function () {
281
- const focused = this.focused;
282
- return pc.dim(` ${getAgentFooterDescription(focused.agentConfiguration)}`);
283
- },
284
- })).agents;
276
+ onCancel: () => process.exit(1),
277
+ });
285
278
  }
286
279
  catch {
287
280
  process.exit(1);
@@ -289,7 +282,7 @@ async function configureAiAgentsHandlerImpl(options) {
289
282
  }
290
283
  else {
291
284
  // non-interactive with explicit --agents: configure all requested
292
- selectedAgents = allAgentChoices.map((a) => a.name);
285
+ selectedAgents = allAgentChoices.map((a) => a.value);
293
286
  }
294
287
  if (selectedAgents?.length === 0) {
295
288
  output_1.output.log({
@@ -388,10 +381,11 @@ function getAgentChoiceForPrompt(agent) {
388
381
  const partiallyConfigured = agent.mcp !== agent.rules;
389
382
  const needsUpdate = partiallyConfigured || agent.outdated;
390
383
  return {
391
- name: agent.name,
392
- message: needsUpdate
384
+ value: agent.name,
385
+ label: needsUpdate
393
386
  ? `${agent.displayName} (update available)`
394
387
  : agent.displayName,
388
+ hint: getAgentFooterDescription(agent),
395
389
  agentConfiguration: agent,
396
390
  };
397
391
  }
@@ -6,7 +6,7 @@ exports.printGenHelp = printGenHelp;
6
6
  exports.generate = generate;
7
7
  const tslib_1 = require("tslib");
8
8
  const pc = tslib_1.__importStar(require("picocolors"));
9
- const enquirer_1 = require("enquirer");
9
+ const prompt_helpers_1 = require("../../utils/prompt-helpers");
10
10
  const path_1 = require("path");
11
11
  const configuration_1 = require("../../config/configuration");
12
12
  const tree_1 = require("../../generators/tree");
@@ -91,42 +91,42 @@ async function promptForCollection(generatorName, interactive, projectsConfigura
91
91
  throwInvalidInvocation(Array.from(choicesMap));
92
92
  }
93
93
  else if (interactive && choices.length > 1) {
94
- const noneOfTheAbove = `\nNone of the above`;
94
+ const noneOfTheAbove = `None of the above`;
95
+ // Blank line before the last entry. The newline has to trail the choice
96
+ // *before* the gap: a leading one would land between the following
97
+ // choice's radio marker and its text, splitting that row in two.
98
+ const beforeGap = choices.length - 1;
95
99
  choices.push(noneOfTheAbove);
96
- let { generator, customCollection } = await (0, enquirer_1.prompt)([
97
- {
98
- name: 'generator',
99
- message: `Which generator would you like to use?`,
100
- type: 'autocomplete',
101
- // enquirer's typings are incorrect here... It supports (string | Choice)[], but is typed as (string[] | Choice[])
102
- choices: choices,
103
- },
104
- {
105
- name: 'customCollection',
106
- type: 'input',
107
- message: `Which collection would you like to use?`,
108
- skip: function () {
109
- // Skip this question if the user did not answer None of the above
110
- return this.state.answers.generator !== noneOfTheAbove;
111
- },
112
- validate: function (value) {
113
- if (this.skipped) {
114
- return true;
115
- }
116
- try {
117
- (0, generator_utils_1.getGeneratorInformation)(value, generatorName, workspace_root_1.workspaceRoot, projectsConfiguration.projects);
118
- return true;
119
- }
120
- catch {
121
- logger_1.logger.error(`\nCould not find ${value}:${generatorName}`);
122
- return false;
123
- }
124
- },
100
+ const generator = await (0, prompt_helpers_1.selectPrompt)({
101
+ message: `Which generator would you like to use?`,
102
+ // Local-plugin entries carry a separate display label; the rest are
103
+ // plain collection names. Only the label takes the newline, so the
104
+ // value still resolves as a collection name.
105
+ choices: choices.map((c, i) => {
106
+ const choice = typeof c === 'string'
107
+ ? { value: c, label: c }
108
+ : { value: c.value, label: c.message };
109
+ return i === beforeGap && !choice.label.endsWith('\n')
110
+ ? { ...choice, label: `${choice.label}\n` }
111
+ : choice;
112
+ }),
113
+ });
114
+ if (generator !== noneOfTheAbove) {
115
+ return generator;
116
+ }
117
+ const customCollection = await (0, prompt_helpers_1.textPrompt)({
118
+ message: `Which collection would you like to use?`,
119
+ validate: (value) => {
120
+ try {
121
+ (0, generator_utils_1.getGeneratorInformation)(value, generatorName, workspace_root_1.workspaceRoot, projectsConfiguration.projects);
122
+ return undefined;
123
+ }
124
+ catch {
125
+ return `Could not find ${value}:${generatorName}`;
126
+ }
125
127
  },
126
- ]);
127
- return customCollection
128
- ? `${customCollection}:${generatorName}`
129
- : generator;
128
+ });
129
+ return `${customCollection}:${generatorName}`;
130
130
  }
131
131
  else if (deprecatedChoices.size > 0) {
132
132
  throw new Error([
@@ -8,7 +8,7 @@ const pc = tslib_1.__importStar(require("picocolors"));
8
8
  const git_utils_1 = require("../../utils/git-utils");
9
9
  const promises_1 = require("node:fs/promises");
10
10
  const tmp_1 = require("tmp");
11
- const enquirer_1 = require("enquirer");
11
+ const prompt_helpers_1 = require("../../utils/prompt-helpers");
12
12
  const output_1 = require("../../utils/output");
13
13
  const createSpinner = require('ora');
14
14
  const init_v2_1 = require("../init/init-v2");
@@ -26,7 +26,6 @@ const configure_plugins_1 = require("../init/configure-plugins");
26
26
  const check_compatible_with_plugins_1 = require("../init/implementation/check-compatible-with-plugins");
27
27
  const native_1 = require("../../native");
28
28
  const ai_output_1 = require("./utils/ai-output");
29
- const init_v2_2 = require("../init/init-v2");
30
29
  const importRemoteName = '__tmp_nx_import__';
31
30
  async function importHandler(options) {
32
31
  process.env.NX_RUNNING_NX_IMPORT = 'true';
@@ -77,14 +76,10 @@ async function importHandler(options) {
77
76
  }
78
77
  const tempImportDirectory = (0, path_1.join)(tmp_1.tmpdir, 'nx-import');
79
78
  if (!sourceRepository) {
80
- sourceRepository = (await (0, enquirer_1.prompt)([
81
- {
82
- type: 'input',
83
- name: 'sourceRepository',
84
- message: 'What is the URL of the repository you want to import? (This can be a local git repository or a git remote URL)',
85
- required: true,
86
- },
87
- ])).sourceRepository;
79
+ sourceRepository = await (0, prompt_helpers_1.textPrompt)({
80
+ message: 'What is the URL of the repository you want to import? (This can be a local git repository or a git remote URL)',
81
+ validate: (value) => (value ? undefined : 'A repository is required'),
82
+ });
88
83
  }
89
84
  try {
90
85
  const maybeLocalDirectory = await (0, promises_1.stat)(sourceRepository);
@@ -132,19 +127,10 @@ async function importHandler(options) {
132
127
  throw new Error('The --ref option is required when running in agent mode.');
133
128
  }
134
129
  const branchChoices = await sourceGitClient.listBranches();
135
- ref = (await (0, enquirer_1.prompt)([
136
- {
137
- type: 'autocomplete',
138
- name: 'ref',
139
- message: `Which branch do you want to import?`,
140
- choices: branchChoices,
141
- /**
142
- * Limit the number of choices so that it fits on screen
143
- */
144
- limit: process.stdout.rows - 3,
145
- required: true,
146
- },
147
- ])).ref;
130
+ ref = await (0, prompt_helpers_1.selectPrompt)({
131
+ message: `Which branch do you want to import?`,
132
+ choices: branchChoices,
133
+ });
148
134
  }
149
135
  if (!source) {
150
136
  if (aiMode) {
@@ -152,28 +138,20 @@ async function importHandler(options) {
152
138
  source = '.';
153
139
  }
154
140
  else {
155
- source = (await (0, enquirer_1.prompt)([
156
- {
157
- type: 'input',
158
- name: 'source',
159
- message: `Which directory do you want to import into this workspace? (leave blank to import the entire repository)`,
160
- },
161
- ])).source;
141
+ source = await (0, prompt_helpers_1.textPrompt)({
142
+ message: `Which directory do you want to import into this workspace? (leave blank to import the entire repository)`,
143
+ });
162
144
  }
163
145
  }
164
146
  if (!destination) {
165
147
  if (aiMode) {
166
148
  throw new Error('The --destination option is required when running in agent mode.');
167
149
  }
168
- destination = (await (0, enquirer_1.prompt)([
169
- {
170
- type: 'input',
171
- name: 'destination',
172
- message: 'Where in this workspace should the code be imported into?',
173
- required: true,
174
- initial: source ? source : undefined,
175
- },
176
- ])).destination;
150
+ destination = await (0, prompt_helpers_1.textPrompt)({
151
+ message: 'Where in this workspace should the code be imported into?',
152
+ initialValue: source ? source : undefined,
153
+ validate: (value) => (value ? undefined : 'A destination is required'),
154
+ });
177
155
  }
178
156
  const absSource = (0, path_1.join)(sourceTempRepoPath, source);
179
157
  if ((0, path_1.isAbsolute)(destination)) {
@@ -361,7 +339,7 @@ async function importHandler(options) {
361
339
  (0, ai_output_1.writeAiOutput)((0, ai_output_1.buildImportNeedsPluginSelectionResult)({
362
340
  detectedPlugins: detectedButNotInstalled.map((name) => ({
363
341
  name,
364
- reason: (0, init_v2_2.getPluginReason)(name),
342
+ reason: (0, init_v2_1.getPluginReason)(name),
365
343
  })),
366
344
  sourceRepository,
367
345
  ref,
@@ -1,12 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.determineAiAgents = determineAiAgents;
4
- const tslib_1 = require("tslib");
5
- const enquirer_1 = require("enquirer");
4
+ const prompt_helpers_1 = require("../../utils/prompt-helpers");
6
5
  const is_ci_1 = require("../../utils/is-ci");
7
6
  const utils_1 = require("../../ai/utils");
8
7
  const detect_ai_agent_1 = require("../../ai/detect-ai-agent");
9
- const pc = tslib_1.__importStar(require("picocolors"));
10
8
  async function determineAiAgents(aiAgents, interactive) {
11
9
  if (aiAgents) {
12
10
  const filtered = aiAgents.filter((a) => a !== 'none');
@@ -22,15 +20,11 @@ async function determineAiAgents(aiAgents, interactive) {
22
20
  return await aiAgentsPrompt();
23
21
  }
24
22
  async function aiAgentsPrompt() {
25
- const promptConfig = {
26
- name: 'agents',
23
+ return (0, prompt_helpers_1.multiselectPrompt)({
27
24
  message: 'Which AI agents, if any, would you like to set up?',
28
- type: 'multiselect',
29
25
  choices: utils_1.supportedAgents.map((a) => ({
30
- name: a,
31
- message: utils_1.agentDisplayMap[a],
26
+ value: a,
27
+ label: utils_1.agentDisplayMap[a],
32
28
  })),
33
- footer: () => pc.dim('Multiple selections possible. <Space> to select. <Enter> to confirm.'),
34
- };
35
- return (await (0, enquirer_1.prompt)([promptConfig])).agents;
29
+ });
36
30
  }
@@ -17,8 +17,10 @@ exports.yargsInitCommand = {
17
17
  return withInitOptions(yargs);
18
18
  },
19
19
  handler: async (args) => {
20
- // Node 24 has stricter readline behavior, and enquirer is not checking for closed state
21
- // when invoking operations, thus you get an ERR_USE_AFTER_CLOSE error.
20
+ // Node 24's stricter readline throws ERR_USE_AFTER_CLOSE when a prompt
21
+ // library operates on a closed interface. Added for enquirer, which nx no
22
+ // longer uses; verify against Node 24 before removing.
23
+ // TODO(v24): drop if @clack/prompts proves not to need it.
22
24
  process.on('uncaughtException', (error) => {
23
25
  if (error &&
24
26
  typeof error === 'object' &&
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addNxToMonorepo = addNxToMonorepo;
4
- const enquirer_1 = require("enquirer");
4
+ const prompt_helpers_1 = require("../../../utils/prompt-helpers");
5
5
  const fs_1 = require("fs");
6
6
  const ignore = require("ignore");
7
7
  const path_1 = require("path");
@@ -23,38 +23,18 @@ async function addNxToMonorepo(options, guided = true) {
23
23
  output_1.output.log({
24
24
  title: '🧑‍🔧 Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration',
25
25
  });
26
- targetDefaults = (await (0, enquirer_1.prompt)([
27
- {
28
- type: 'multiselect',
29
- name: 'targetDefaults',
30
- message: 'Which scripts need to be run in order? (e.g. before building a project, dependent projects must be built)',
31
- choices: scripts,
32
- /**
33
- * limit is missing from the interface but it limits the amount of options shown
34
- */
35
- limit: process.stdout.rows - 4, // 4 leaves room for the header above, the prompt and some whitespace
36
- },
37
- ])).targetDefaults;
38
- cacheableOperations = (await (0, enquirer_1.prompt)([
39
- {
40
- type: 'multiselect',
41
- name: 'cacheableOperations',
42
- message: 'Which scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
43
- choices: scripts,
44
- /**
45
- * limit is missing from the interface but it limits the amount of options shown
46
- */
47
- limit: process.stdout.rows - 4, // 4 leaves room for the header above, the prompt and some whitespace
48
- },
49
- ])).cacheableOperations;
26
+ targetDefaults = await (0, prompt_helpers_1.multiselectPrompt)({
27
+ message: 'Which scripts need to be run in order? (e.g. before building a project, dependent projects must be built)',
28
+ choices: scripts,
29
+ });
30
+ cacheableOperations = await (0, prompt_helpers_1.multiselectPrompt)({
31
+ message: 'Which scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
32
+ choices: scripts,
33
+ });
50
34
  for (const scriptName of cacheableOperations) {
51
- scriptOutputs[scriptName] = (await (0, enquirer_1.prompt)([
52
- {
53
- type: 'input',
54
- name: scriptName,
55
- message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path relative to a project root (e.g. dist, lib, build, coverage)`,
56
- },
57
- ]))[scriptName];
35
+ scriptOutputs[scriptName] = await (0, prompt_helpers_1.textPrompt)({
36
+ message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path relative to a project root (e.g. dist, lib, build, coverage)`,
37
+ });
58
38
  }
59
39
  nxCloudChoice =
60
40
  options.nxCloud === true
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addNxToNest = addNxToNest;
4
- const tslib_1 = require("tslib");
5
- const enquirer = tslib_1.__importStar(require("enquirer"));
4
+ const prompt_helpers_1 = require("../../../utils/prompt-helpers");
6
5
  const node_fs_1 = require("node:fs");
7
6
  const path_1 = require("path");
8
7
  const fileutils_1 = require("../../../utils/fileutils");
@@ -46,26 +45,14 @@ async function addNxToNest(options, packageJson) {
46
45
  output_1.output.log({
47
46
  title: '🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
48
47
  });
49
- cacheableOperations = (await enquirer.prompt([
50
- {
51
- type: 'multiselect',
52
- name: 'cacheableOperations',
53
- message: 'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
54
- choices: scripts,
55
- /**
56
- * limit is missing from the interface but it limits the amount of options shown
57
- */
58
- limit: process.stdout.rows - 4, // 4 leaves room for the header above, the prompt and some whitespace
59
- },
60
- ])).cacheableOperations;
48
+ cacheableOperations = await (0, prompt_helpers_1.multiselectPrompt)({
49
+ message: 'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not)',
50
+ choices: scripts,
51
+ });
61
52
  for (const scriptName of cacheableOperations) {
62
- scriptOutputs[scriptName] = (await enquirer.prompt([
63
- {
64
- type: 'input',
65
- name: scriptName,
66
- message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path (e.g. dist, lib, build, coverage)`,
67
- },
68
- ]))[scriptName];
53
+ scriptOutputs[scriptName] = await (0, prompt_helpers_1.textPrompt)({
54
+ message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path (e.g. dist, lib, build, coverage)`,
55
+ });
69
56
  }
70
57
  nxCloudChoice =
71
58
  options.nxCloud === true
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addNxToNpmRepo = addNxToNpmRepo;
4
- const tslib_1 = require("tslib");
5
- const enquirer = tslib_1.__importStar(require("enquirer"));
4
+ const prompt_helpers_1 = require("../../../utils/prompt-helpers");
6
5
  const path_1 = require("path");
7
6
  const fileutils_1 = require("../../../utils/fileutils");
8
7
  const output_1 = require("../../../utils/output");
@@ -21,26 +20,14 @@ async function addNxToNpmRepo(options, guided = true) {
21
20
  output_1.output.log({
22
21
  title: '🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
23
22
  });
24
- cacheableOperations = (await enquirer.prompt([
25
- {
26
- type: 'multiselect',
27
- name: 'cacheableOperations',
28
- message: 'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not). You can use spacebar to select one or more scripts.',
29
- choices: scripts,
30
- /**
31
- * limit is missing from the interface but it limits the amount of options shown
32
- */
33
- limit: process.stdout.rows - 4, // 4 leaves room for the header above, the prompt and some whitespace
34
- },
35
- ])).cacheableOperations;
23
+ cacheableOperations = await (0, prompt_helpers_1.multiselectPrompt)({
24
+ message: 'Which of the following scripts are cacheable? (Produce the same output given the same input, e.g. build, test and lint usually are, serve and start are not). You can use spacebar to select one or more scripts.',
25
+ choices: scripts,
26
+ });
36
27
  for (const scriptName of cacheableOperations) {
37
- scriptOutputs[scriptName] = (await enquirer.prompt([
38
- {
39
- type: 'input',
40
- name: scriptName,
41
- message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path (e.g. dist, lib, build, coverage)`,
42
- },
43
- ]))[scriptName];
28
+ scriptOutputs[scriptName] = await (0, prompt_helpers_1.textPrompt)({
29
+ message: `Does the "${scriptName}" script create any outputs? If not, leave blank, otherwise provide a path (e.g. dist, lib, build, coverage)`,
30
+ });
44
31
  }
45
32
  nxCloudChoice =
46
33
  options.nxCloud === true