nx 23.0.0-beta.17 → 23.0.0-beta.19

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 (84) hide show
  1. package/dist/bin/init-local.js +11 -20
  2. package/dist/bin/nx.js +25 -2
  3. package/dist/src/command-line/add/completion.d.ts +1 -0
  4. package/dist/src/command-line/add/completion.js +15 -0
  5. package/dist/src/command-line/affected/completion.d.ts +1 -0
  6. package/dist/src/command-line/affected/completion.js +15 -0
  7. package/dist/src/command-line/completion/argv-layout.d.ts +6 -0
  8. package/dist/src/command-line/completion/argv-layout.js +19 -0
  9. package/dist/src/command-line/completion/command-completions.d.ts +19 -0
  10. package/dist/src/command-line/completion/command-completions.js +120 -0
  11. package/dist/src/command-line/completion/command-handlers.d.ts +30 -0
  12. package/dist/src/command-line/completion/command-handlers.js +69 -0
  13. package/dist/src/command-line/completion/command-object.d.ts +10 -0
  14. package/dist/src/command-line/completion/command-object.js +95 -0
  15. package/dist/src/command-line/completion/completion-providers.d.ts +21 -0
  16. package/dist/src/command-line/completion/completion-providers.js +194 -0
  17. package/dist/src/command-line/completion/infix-targets.d.ts +1 -0
  18. package/dist/src/command-line/completion/infix-targets.js +48 -0
  19. package/dist/src/command-line/completion/metadata.d.ts +22 -0
  20. package/dist/src/command-line/completion/metadata.js +71 -0
  21. package/dist/src/command-line/completion/registrations.d.ts +9 -0
  22. package/dist/src/command-line/completion/registrations.js +16 -0
  23. package/dist/src/command-line/completion/scripts/bash.sh +51 -0
  24. package/dist/src/command-line/completion/scripts/fish.fish +47 -0
  25. package/dist/src/command-line/completion/scripts/powershell.ps1 +52 -0
  26. package/dist/src/command-line/completion/scripts/zsh.zsh +69 -0
  27. package/dist/src/command-line/completion/scripts.d.ts +18 -0
  28. package/dist/src/command-line/completion/scripts.js +140 -0
  29. package/dist/src/command-line/completion/trigger.d.ts +3 -0
  30. package/dist/src/command-line/completion/trigger.js +21 -0
  31. package/dist/src/command-line/completion/value-completions.d.ts +3 -0
  32. package/dist/src/command-line/completion/value-completions.js +21 -0
  33. package/dist/src/command-line/generate/completion.d.ts +1 -0
  34. package/dist/src/command-line/generate/completion.js +9 -0
  35. package/dist/src/command-line/graph/completion.d.ts +1 -0
  36. package/dist/src/command-line/graph/completion.js +13 -0
  37. package/dist/src/command-line/migrate/migrate.js +2 -1
  38. package/dist/src/command-line/migrate/prompt-files.d.ts +19 -0
  39. package/dist/src/command-line/migrate/prompt-files.js +40 -6
  40. package/dist/src/command-line/nx-commands.js +9 -0
  41. package/dist/src/command-line/report/report.js +2 -1
  42. package/dist/src/command-line/run/completion.d.ts +1 -0
  43. package/dist/src/command-line/run/completion.js +7 -0
  44. package/dist/src/command-line/run-many/completion.d.ts +1 -0
  45. package/dist/src/command-line/run-many/completion.js +13 -0
  46. package/dist/src/command-line/show/completion.d.ts +1 -0
  47. package/dist/src/command-line/show/completion.js +27 -0
  48. package/dist/src/command-line/watch/completion.d.ts +1 -0
  49. package/dist/src/command-line/watch/completion.js +10 -0
  50. package/dist/src/config/schema-utils.d.ts +21 -0
  51. package/dist/src/config/schema-utils.js +82 -13
  52. package/dist/src/core/graph/main.js +1 -1
  53. package/dist/src/devkit-internals.d.ts +2 -0
  54. package/dist/src/devkit-internals.js +9 -1
  55. package/dist/src/migrations/update-17-0-0/move-cache-directory.md +31 -0
  56. package/dist/src/migrations/update-20-0-0/move-use-daemon-process.md +27 -0
  57. package/dist/src/migrations/update-20-0-1/use-legacy-cache.md +24 -0
  58. package/dist/src/migrations/update-21-0-0/release-changelog-config-changes.md +49 -0
  59. package/dist/src/migrations/update-21-0-0/release-version-config-changes.md +54 -0
  60. package/dist/src/migrations/update-21-0-0/remove-custom-tasks-runner.md +28 -0
  61. package/dist/src/migrations/update-21-0-0/remove-legacy-cache.md +22 -0
  62. package/dist/src/migrations/update-22-2-0/add-self-healing-to-gitignore.md +11 -0
  63. package/dist/src/migrations/update-23-0-0/convert-target-defaults-to-array.md +66 -0
  64. package/dist/src/native/index.d.ts +1 -1
  65. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  66. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  67. package/dist/src/plugins/js/utils/packages.js +1 -1
  68. package/dist/src/project-graph/plugins/resolve-plugin.js +4 -24
  69. package/dist/src/tasks-runner/create-task-graph.js +1 -1
  70. package/dist/src/tasks-runner/default-tasks-runner.d.ts +0 -2
  71. package/dist/src/tasks-runner/task-orchestrator.js +4 -6
  72. package/dist/src/tasks-runner/utils.d.ts +0 -4
  73. package/dist/src/tasks-runner/utils.js +0 -10
  74. package/dist/src/utils/fileutils.d.ts +0 -8
  75. package/dist/src/utils/fileutils.js +0 -40
  76. package/dist/src/utils/nx-package-group.d.ts +8 -0
  77. package/dist/src/utils/nx-package-group.js +15 -0
  78. package/dist/src/utils/package-json.d.ts +13 -0
  79. package/dist/src/utils/package-json.js +7 -4
  80. package/dist/src/utils/plugins/local-plugins.d.ts +18 -0
  81. package/dist/src/utils/plugins/local-plugins.js +30 -0
  82. package/dist/src/utils/tar.d.ts +8 -0
  83. package/dist/src/utils/tar.js +44 -0
  84. package/package.json +11 -11
@@ -30,13 +30,18 @@ async function initLocal(workspace) {
30
30
  handleAngularCLIFallbacks(workspace);
31
31
  return;
32
32
  }
33
- // Ensure NxConsole is installed if the user has it configured.
34
- try {
35
- await ensureNxConsoleInstalledViaDaemon();
33
+ // Skip per-TAB shell completion calls those must not spawn the daemon.
34
+ if (!process.env.NX_COMPLETE) {
35
+ try {
36
+ await ensureNxConsoleInstalledViaDaemon();
37
+ }
38
+ catch { }
36
39
  }
37
- catch { }
38
40
  const command = process.argv[2];
39
- if (command === 'run' || command === 'g' || command === 'generate') {
41
+ if (command === 'completion' ||
42
+ command === 'run' ||
43
+ command === 'g' ||
44
+ command === 'generate') {
40
45
  nx_commands_1.commandsObject.parse(process.argv.slice(2));
41
46
  }
42
47
  else if (isKnownCommand(command)) {
@@ -110,14 +115,7 @@ function isKnownCommand(command) {
110
115
  }
111
116
  function shouldDelegateToAngularCLI() {
112
117
  const command = process.argv[2];
113
- const commands = [
114
- 'analytics',
115
- 'cache',
116
- 'completion',
117
- 'config',
118
- 'doc',
119
- 'update',
120
- ];
118
+ const commands = ['analytics', 'cache', 'config', 'doc', 'update'];
121
119
  return commands.indexOf(command) > -1;
122
120
  }
123
121
  async function ensureNxConsoleInstalledViaDaemon() {
@@ -169,13 +167,6 @@ function handleAngularCLIFallbacks(workspace) {
169
167
  console.log(`Running "ng update" can still be useful in some dev workflows, so we aren't planning to remove it.`);
170
168
  console.log(`If you need to use it, run "FORCE_NG_UPDATE=true ng update".`);
171
169
  }
172
- else if (process.argv[2] === 'completion') {
173
- if (!process.argv[3]) {
174
- console.log(`"ng completion" is not natively supported by Nx.
175
- Instead, you could try an Nx Editor Plugin for a visual tool to run Nx commands. If you're using VSCode, you can use the Nx Console plugin, or if you're using WebStorm, you could use one of the available community plugins.
176
- For more information, see https://nx.dev/getting-started/editor-setup`);
177
- }
178
- }
179
170
  else if (process.argv[2] === 'cache') {
180
171
  console.log(`"ng cache" is not natively supported by Nx.
181
172
  To clear the cache, you can delete the ".angular/cache" directory (or the directory configured by "cli.cache.path" in the "nx.json" file).
package/dist/bin/nx.js CHANGED
@@ -29,10 +29,32 @@ require("../src/utils/perf-logging");
29
29
  const isTsExt = (0, path_1.extname)(__filename).endsWith('.ts');
30
30
  const pathToPkgJson = isTsExt ? '../package.json' : '../../package.json';
31
31
  async function main() {
32
+ // Tab-completion fast path. Bare env-var read so nothing runs before
33
+ // the try/catch — a throw here would splice a stack trace into the
34
+ // user's command line.
35
+ if (process.env.NX_COMPLETE) {
36
+ try {
37
+ perf_hooks_1.performance.mark('init-local');
38
+ const { tryValueCompletion } = await import('nx/src/command-line/completion/value-completions');
39
+ if (tryValueCompletion())
40
+ return;
41
+ const { tryCommandSurfaceCompletion } = await import('nx/src/command-line/completion/command-completions');
42
+ tryCommandSurfaceCompletion();
43
+ }
44
+ catch (e) {
45
+ // Swallow: a broken completion must produce no suggestions, not a
46
+ // stack trace. NX_VERBOSE_LOGGING surfaces the cause to stderr.
47
+ if (process.env.NX_VERBOSE_LOGGING) {
48
+ console.error(e);
49
+ }
50
+ }
51
+ return;
52
+ }
32
53
  if (process.argv[2] !== 'report' &&
33
54
  process.argv[2] !== '--version' &&
34
55
  process.argv[2] !== '--help' &&
35
- process.argv[2] !== 'reset') {
56
+ process.argv[2] !== 'reset' &&
57
+ process.argv[2] !== 'completion') {
36
58
  const { assertSupportedPlatform } = await import('../src/native/assert-supported-platform.js');
37
59
  assertSupportedPlatform();
38
60
  }
@@ -55,6 +77,7 @@ async function main() {
55
77
  process.argv[2] === 'init' ||
56
78
  process.argv[2] === 'configure-ai-agents' ||
57
79
  process.argv[2] === 'mcp' ||
80
+ process.argv[2] === 'completion' ||
58
81
  (process.argv[2] === 'graph' && !workspace)) {
59
82
  process.env.NX_DAEMON = 'false';
60
83
  (await import('nx/src/command-line/nx-commands')).commandsObject.argv;
@@ -213,7 +236,7 @@ function handleMissingLocalInstallation(detectedWorkspaceRoot) {
213
236
  * Warns if out of date by 1 major version or more.
214
237
  */
215
238
  function warnIfUsingOutdatedGlobalInstall(globalNxVersion, localNxVersion) {
216
- // Never display this warning if Nx is already running via Nx
239
+ // Skip when Nx is recursively invoking itself.
217
240
  if (process.env.NX_CLI_SET) {
218
241
  return;
219
242
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const metadata_1 = require("../completion/metadata");
4
+ const nx_package_group_1 = require("../../utils/nx-package-group");
5
+ // Same list `nx report` uses. Filter to first-party plugins and sort.
6
+ const FIRST_PARTY_PLUGINS = (0, nx_package_group_1.readNxPackageGroup)()
7
+ .filter((p) => p.startsWith('@nx/'))
8
+ .sort();
9
+ (0, metadata_1.registerCompletion)('add', {
10
+ positionals: [
11
+ {
12
+ complete: (current) => FIRST_PARTY_PLUGINS.filter((p) => p.startsWith(current)),
13
+ },
14
+ ],
15
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const metadata_1 = require("../completion/metadata");
4
+ const completion_providers_1 = require("../completion/completion-providers");
5
+ // Aliases are written out; the fast path runs before yargs can resolve them.
6
+ (0, metadata_1.registerCompletion)('affected', {
7
+ flags: {
8
+ projects: completion_providers_1.getProjectNameCompletions,
9
+ p: completion_providers_1.getProjectNameCompletions,
10
+ exclude: completion_providers_1.getProjectNameCompletions,
11
+ targets: completion_providers_1.getTargetNameCompletions,
12
+ target: completion_providers_1.getTargetNameCompletions,
13
+ t: completion_providers_1.getTargetNameCompletions,
14
+ },
15
+ });
@@ -0,0 +1,6 @@
1
+ export interface ParsedCompletionArgs {
2
+ tokens: string[];
3
+ current: string;
4
+ previousToken: string;
5
+ }
6
+ export declare function parseCompletionArgs(argv?: readonly string[]): ParsedCompletionArgs | null;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ // Wrappers must invoke nx with argv: [node, nx-bin, ...tokens, currentPartial].
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseCompletionArgs = parseCompletionArgs;
5
+ function parseCompletionArgs(argv = process.argv) {
6
+ const tail = argv.slice(2);
7
+ // Wrappers usually prepend the literal 'nx' (from COMP_WORDS /
8
+ // commandline -cop / etc.). They sometimes don't — most notably the
9
+ // `.nx/installation` wrapper invokes the real bin directly without the
10
+ // 'nx' token, and manual invocations like `NX_COMPLETE=fish nx show
11
+ // target in` for dev testing skip it too. Strip when present, otherwise
12
+ // take the args as-is.
13
+ const tokens = tail[0] === 'nx' ? tail.slice(1) : tail;
14
+ if (tokens.length === 0)
15
+ return null;
16
+ const current = tokens[tokens.length - 1] ?? '';
17
+ const previousToken = tokens.length >= 2 ? tokens[tokens.length - 2] : '';
18
+ return { tokens, current, previousToken };
19
+ }
@@ -0,0 +1,19 @@
1
+ /** Slow-path entry point. Returns true if anything was emitted. */
2
+ export declare function tryCommandSurfaceCompletion(argv?: readonly string[]): boolean;
3
+ /** Top-level command names. Unions yargs handlers with the completion
4
+ * registry's single-token paths (infix targets). */
5
+ export declare function getTopLevelCommands(current: string, withDesc: boolean): string[] | null;
6
+ /**
7
+ * Enumerates subcommands + options of a matched top-level command. Returns
8
+ * null when no top-level command name is matched in `args`.
9
+ */
10
+ export declare function getCommandCompletions(current: string, args: string[]): string[] | null;
11
+ /** value\tdescription separator. TAB because completion values can contain
12
+ * colons (`my-app:build`); descriptions get TABs collapsed. */
13
+ export declare const DESC_SEPARATOR = "\t";
14
+ /** Strip the y18n marker yargs prepends to its built-in --help / --version
15
+ * descriptions, and collapse stray TABs so they can't forge the
16
+ * value/description separator. */
17
+ export declare function formatDescription(raw: string | undefined): string;
18
+ /** zsh (compadd -d) and fish (complete -a) parse `value\tdescription`. */
19
+ export declare function shellRendersDescriptions(): boolean;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ // Slow-path completion: command/subcommand/flag names. Runs after
3
+ // tryValueCompletion has nothing to offer.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.DESC_SEPARATOR = void 0;
6
+ exports.tryCommandSurfaceCompletion = tryCommandSurfaceCompletion;
7
+ exports.getTopLevelCommands = getTopLevelCommands;
8
+ exports.getCommandCompletions = getCommandCompletions;
9
+ exports.formatDescription = formatDescription;
10
+ exports.shellRendersDescriptions = shellRendersDescriptions;
11
+ const trigger_1 = require("./trigger");
12
+ const argv_layout_1 = require("./argv-layout");
13
+ const metadata_1 = require("./metadata");
14
+ const command_handlers_1 = require("./command-handlers");
15
+ /** Slow-path entry point. Returns true if anything was emitted. */
16
+ function tryCommandSurfaceCompletion(argv = process.argv) {
17
+ const parsed = (0, argv_layout_1.parseCompletionArgs)(argv);
18
+ if (parsed === null)
19
+ return false;
20
+ const matched = getCommandCompletions(parsed.current, parsed.tokens);
21
+ const completions = matched !== null
22
+ ? matched
23
+ : getTopLevelCommands(parsed.current, shellRendersDescriptions());
24
+ if (completions === null || completions.length === 0)
25
+ return false;
26
+ for (const line of completions) {
27
+ console.log(line);
28
+ }
29
+ return true;
30
+ }
31
+ /** Top-level command names. Unions yargs handlers with the completion
32
+ * registry's single-token paths (infix targets). */
33
+ function getTopLevelCommands(current, withDesc) {
34
+ const handlers = (0, command_handlers_1.getNxCommandHandlers)();
35
+ const seen = new Set();
36
+ const completions = [];
37
+ for (const name of Object.keys(handlers)) {
38
+ if (name === '$0' || name.startsWith('_'))
39
+ continue;
40
+ if (current && !name.startsWith(current))
41
+ continue;
42
+ const handler = handlers[name];
43
+ if (handler?.description === false)
44
+ continue; // hidden
45
+ seen.add(name);
46
+ const desc = withDesc ? formatDescription(handler?.description) : '';
47
+ completions.push(desc ? `${name}${exports.DESC_SEPARATOR}${desc}` : name);
48
+ }
49
+ // Infix targets + any other top-level completion-only paths.
50
+ for (const name of (0, metadata_1.getRegisteredTopLevelPaths)()) {
51
+ if (seen.has(name))
52
+ continue;
53
+ if (current && !name.startsWith(current))
54
+ continue;
55
+ seen.add(name);
56
+ completions.push(name);
57
+ }
58
+ return completions;
59
+ }
60
+ /**
61
+ * Enumerates subcommands + options of a matched top-level command. Returns
62
+ * null when no top-level command name is matched in `args`.
63
+ */
64
+ function getCommandCompletions(current, args) {
65
+ const handlers = (0, command_handlers_1.getNxCommandHandlers)();
66
+ const cmdName = args.find((a) => handlers[a]);
67
+ if (!cmdName) {
68
+ return null;
69
+ }
70
+ const handler = handlers[cmdName];
71
+ // Once we recognize a top-level command in `args`, we own the slot —
72
+ // return [] (not null) for the "found a command but can't enumerate its
73
+ // surface" case so the caller doesn't fall back to top-level commands
74
+ // (which would mis-offer e.g. `exec` for `nx g c ex`).
75
+ if (typeof handler.builder !== 'function') {
76
+ return [];
77
+ }
78
+ const intro = (0, command_handlers_1.introspectBuilder)(handler.builder);
79
+ if (!intro)
80
+ return [];
81
+ const completions = [];
82
+ const isFlagPrefix = current.startsWith('-');
83
+ const withDesc = shellRendersDescriptions();
84
+ if (!isFlagPrefix) {
85
+ for (const [name, desc] of intro.subcommands) {
86
+ const formatted = withDesc ? formatDescription(desc) : '';
87
+ completions.push(formatted ? `${name}${exports.DESC_SEPARATOR}${formatted}` : name);
88
+ }
89
+ }
90
+ for (const [name, desc] of intro.options) {
91
+ const formatted = withDesc ? formatDescription(desc) : '';
92
+ completions.push(formatted ? `--${name}${exports.DESC_SEPARATOR}${formatted}` : `--${name}`);
93
+ }
94
+ if (!current) {
95
+ return completions;
96
+ }
97
+ const flagName = current.replace(/^-+/, '');
98
+ return completions.filter((c) => {
99
+ if (isFlagPrefix) {
100
+ return c.startsWith(`--${flagName}`);
101
+ }
102
+ return c.startsWith(current);
103
+ });
104
+ }
105
+ /** value\tdescription separator. TAB because completion values can contain
106
+ * colons (`my-app:build`); descriptions get TABs collapsed. */
107
+ exports.DESC_SEPARATOR = '\t';
108
+ /** Strip the y18n marker yargs prepends to its built-in --help / --version
109
+ * descriptions, and collapse stray TABs so they can't forge the
110
+ * value/description separator. */
111
+ function formatDescription(raw) {
112
+ if (!raw)
113
+ return '';
114
+ return raw.replace(/^__yargsString__:/, '').replace(/\t/g, ' ');
115
+ }
116
+ /** zsh (compadd -d) and fish (complete -a) parse `value\tdescription`. */
117
+ function shellRendersDescriptions() {
118
+ const shell = (0, trigger_1.getCompletionShell)();
119
+ return shell === 'zsh' || shell === 'fish';
120
+ }
@@ -0,0 +1,30 @@
1
+ /** A single entry from yargs' `getCommandHandlers()`. */
2
+ export interface CommandHandler {
3
+ description?: string | false;
4
+ builder?: (yargs: any) => any;
5
+ }
6
+ export type CommandHandlers = Record<string, CommandHandler>;
7
+ /**
8
+ * Reach into the yargs commandsObject to enumerate registered command
9
+ * handlers. Lazy-required: nx-commands pulls in the full command tree
10
+ * and is only needed on the slow path.
11
+ *
12
+ * Yargs only keys handlers by canonical name. We mirror each alias to its
13
+ * canonical handler reference so lookups like `handlers['g']` resolve to
14
+ * the same entry as `handlers['generate']`.
15
+ */
16
+ export declare function getNxCommandHandlers(): CommandHandlers;
17
+ /** Subcommand name → description, visible-option name → description, and
18
+ * canonical option name → its yargs-declared aliases (e.g. projects → [p]). */
19
+ export interface BuilderIntrospection {
20
+ subcommands: Map<string, string | undefined>;
21
+ options: Map<string, string | undefined>;
22
+ aliases: Map<string, string[]>;
23
+ }
24
+ /**
25
+ * Run a yargs builder against a throwaway instance and return its declared
26
+ * subcommands, visible options, and option-alias groups. Returns null if
27
+ * the builder throws. Does NOT call `.argv` — would trigger parse and the
28
+ * help-printing path we're avoiding.
29
+ */
30
+ export declare function introspectBuilder(builder: (yargs: any) => any): BuilderIntrospection | null;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNxCommandHandlers = getNxCommandHandlers;
4
+ exports.introspectBuilder = introspectBuilder;
5
+ /**
6
+ * Reach into the yargs commandsObject to enumerate registered command
7
+ * handlers. Lazy-required: nx-commands pulls in the full command tree
8
+ * and is only needed on the slow path.
9
+ *
10
+ * Yargs only keys handlers by canonical name. We mirror each alias to its
11
+ * canonical handler reference so lookups like `handlers['g']` resolve to
12
+ * the same entry as `handlers['generate']`.
13
+ */
14
+ function getNxCommandHandlers() {
15
+ const { commandsObject } = require('../nx-commands');
16
+ const internal = commandsObject.getInternalMethods();
17
+ const handlers = { ...internal.getCommandInstance().getCommandHandlers() };
18
+ for (const row of internal.getUsageInstance().getCommands()) {
19
+ // usage.getCommands() rows: [usagePattern, description, isDefault, aliases, deprecated]
20
+ const usagePattern = String(row[0] ?? '');
21
+ const aliases = Array.isArray(row[3]) ? row[3] : [];
22
+ const canonical = usagePattern.split(/\s+/)[0];
23
+ const handler = handlers[canonical];
24
+ if (!handler)
25
+ continue;
26
+ for (const alias of aliases) {
27
+ if (!handlers[alias])
28
+ handlers[alias] = handler;
29
+ }
30
+ }
31
+ return handlers;
32
+ }
33
+ /**
34
+ * Run a yargs builder against a throwaway instance and return its declared
35
+ * subcommands, visible options, and option-alias groups. Returns null if
36
+ * the builder throws. Does NOT call `.argv` — would trigger parse and the
37
+ * help-printing path we're avoiding.
38
+ */
39
+ function introspectBuilder(builder) {
40
+ const yargs = require('yargs');
41
+ const temp = yargs();
42
+ try {
43
+ builder(temp);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ const usage = temp.getInternalMethods().getUsageInstance();
49
+ const subcommands = new Map();
50
+ for (const [usagePattern, desc] of usage.getCommands()) {
51
+ const name = String(usagePattern).split(/\s+/)[0];
52
+ if (name === '$0')
53
+ continue;
54
+ subcommands.set(name, desc);
55
+ }
56
+ const opts = temp.getOptions();
57
+ const descriptions = usage.getDescriptions();
58
+ const options = new Map();
59
+ for (const k of Object.keys(opts.key ?? {})) {
60
+ if ((opts.hiddenOptions ?? []).includes(k))
61
+ continue;
62
+ options.set(k, descriptions[k]);
63
+ }
64
+ const aliases = new Map();
65
+ for (const [canonical, list] of Object.entries(opts.alias ?? {})) {
66
+ aliases.set(canonical, list);
67
+ }
68
+ return { subcommands, options, aliases };
69
+ }
@@ -0,0 +1,10 @@
1
+ import { CommandModule } from 'yargs';
2
+ declare const SHELL_CHOICES: readonly ["bash", "zsh", "fish", "powershell"];
3
+ type Shell = (typeof SHELL_CHOICES)[number];
4
+ interface CompletionArgs {
5
+ shell?: Shell;
6
+ force?: boolean;
7
+ stdout?: boolean;
8
+ }
9
+ export declare const yargsCompletionCommand: CommandModule<{}, CompletionArgs>;
10
+ export {};
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.yargsCompletionCommand = void 0;
4
+ const enquirer_1 = require("enquirer");
5
+ const fs_1 = require("fs");
6
+ const os_1 = require("os");
7
+ const path_1 = require("path");
8
+ const handle_import_1 = require("../../utils/handle-import");
9
+ const SHELL_CHOICES = ['bash', 'zsh', 'fish', 'powershell'];
10
+ exports.yargsCompletionCommand = {
11
+ command: 'completion [shell]',
12
+ describe: 'Install shell completion for bash, zsh, fish, or powershell. Omit the shell to pick interactively.',
13
+ builder: (yargs) => yargs
14
+ .positional('shell', {
15
+ type: 'string',
16
+ choices: SHELL_CHOICES,
17
+ describe: 'Shell to install completion for.',
18
+ })
19
+ .option('force', {
20
+ type: 'boolean',
21
+ default: false,
22
+ describe: 'Install the completion script even if `nx` is not found on PATH.',
23
+ })
24
+ .option('stdout', {
25
+ type: 'boolean',
26
+ default: false,
27
+ describe: 'Print the completion script to stdout instead of writing to the shell rc file.',
28
+ })
29
+ .example('$0 completion bash', 'Install bash completion to ~/.bashrc')
30
+ .example('$0 completion', 'Pick shells interactively and install completion for each')
31
+ .example('$0 completion bash --stdout >> ~/.bash_profile', 'Print to stdout for a custom rc location'),
32
+ handler: async (args) => {
33
+ const scripts = await (0, handle_import_1.handleImport)('./scripts.js', __dirname);
34
+ const shells = args.shell ? [args.shell] : await pickShellsInteractively();
35
+ if (shells.length === 0) {
36
+ console.warn('nx: no shells selected — nothing installed.');
37
+ process.exit(0);
38
+ }
39
+ if (args.stdout && shells.length > 1) {
40
+ console.warn('nx: --stdout only makes sense with one shell — concatenating two wrapper scripts to stdout is never useful.');
41
+ process.exit(1);
42
+ }
43
+ const emit = args.stdout
44
+ ? scripts.printCompletionScript
45
+ : scripts.installCompletionScript;
46
+ // Fire the PATH-advisory once, before any per-shell emit.
47
+ if (!args.force)
48
+ scripts.maybeWarnNxNotOnPath();
49
+ for (const shell of shells)
50
+ emit(shell);
51
+ process.exit(0);
52
+ },
53
+ };
54
+ async function pickShellsInteractively() {
55
+ if (!process.stdin.isTTY || !process.stderr.isTTY) {
56
+ console.warn('nx: please specify a shell — `nx completion <bash|zsh|fish|powershell>`.');
57
+ process.exit(1);
58
+ }
59
+ const detected = detectAvailableShells();
60
+ const answer = (await (0, enquirer_1.prompt)({
61
+ type: 'multiselect',
62
+ name: 'shells',
63
+ message: 'Install nx completion for which shell(s)?',
64
+ choices: SHELL_CHOICES.map((name) => ({
65
+ name,
66
+ value: name,
67
+ // Pre-check shells we can detect on this machine.
68
+ enabled: detected.has(name),
69
+ })),
70
+ }));
71
+ return answer.shells ?? [];
72
+ }
73
+ /** Best-effort detect-which-shells-the-user-has. Pre-checks the multiselect.
74
+ * Signals: $SHELL basename, presence of conventional rc files, $PSModulePath
75
+ * for PowerShell. False positives are fine — the user can uncheck. */
76
+ function detectAvailableShells() {
77
+ const found = new Set();
78
+ const home = (0, os_1.homedir)();
79
+ const shellEnv = (process.env.SHELL ?? '').replace(/\\/g, '/');
80
+ const shellName = shellEnv.split('/').pop() ?? '';
81
+ if (shellName === 'bash' || (0, fs_1.existsSync)((0, path_1.join)(home, '.bashrc'))) {
82
+ found.add('bash');
83
+ }
84
+ if (shellName === 'zsh' || (0, fs_1.existsSync)((0, path_1.join)(home, '.zshrc'))) {
85
+ found.add('zsh');
86
+ }
87
+ if (shellName === 'fish' ||
88
+ (0, fs_1.existsSync)((0, path_1.join)(home, '.config', 'fish', 'config.fish'))) {
89
+ found.add('fish');
90
+ }
91
+ if (process.env.PSModulePath || process.platform === 'win32') {
92
+ found.add('powershell');
93
+ }
94
+ return found;
95
+ }
@@ -0,0 +1,21 @@
1
+ /** Project names matching `current`. */
2
+ export declare function getProjectNameCompletions(current: string): string[];
3
+ /** Projects that declare `targetName`, matching `current`. */
4
+ export declare function getProjectNamesWithTarget(current: string, targetName: string): string[];
5
+ /** Two-stage `project[:target]` — stage 1 emits `project:` (nospace), stage 2 emits `project:target`. */
6
+ export declare function completeProjectTarget(current: string): string[];
7
+ /** Generator completion. Stage 1 (`nx g <TAB>`) emits plugin names (with `:`)
8
+ * and bare generator names (for `nx g application`); stage 2 emits
9
+ * `plugin:generator`. */
10
+ export declare function completeGenerator(current: string): string[];
11
+ /** Plugin names matching `current` — installed npm plugins + workspace-local
12
+ * plugin projects, only those declaring a generator collection. */
13
+ export declare function getGeneratorPluginCompletions(current: string): string[];
14
+ /** Generator names in a single plugin, matching `current`. */
15
+ export declare function getGeneratorsForPlugin(pluginName: string, current: string): string[];
16
+ /** Unique target names across the workspace, matching `current`. */
17
+ export declare function getTargetNameCompletions(current: string): string[];
18
+ /** Target names for a single project, matching `current`. Falls back to
19
+ * workspace-wide if the project isn't in the graph — covers the
20
+ * `project:t<TAB>` case where the user is still typing the project name. */
21
+ export declare function getTargetNamesForProject(current: string, projectName: string): string[];