nx 22.7.0-beta.11 → 22.7.0-beta.13

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 (106) hide show
  1. package/dist/schemas/nx-schema.json +25 -0
  2. package/dist/schemas/project-schema.json +25 -0
  3. package/dist/src/adapter/ngcli-adapter.js +11 -12
  4. package/dist/src/command-line/daemon/daemon.js +8 -4
  5. package/dist/src/command-line/graph/graph.js +8 -1
  6. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +19 -9
  7. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +19 -9
  8. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +19 -9
  9. package/dist/src/command-line/init/implementation/angular/index.js +11 -3
  10. package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +11 -5
  11. package/dist/src/command-line/init/implementation/utils.d.ts +1 -0
  12. package/dist/src/command-line/init/implementation/utils.js +8 -1
  13. package/dist/src/command-line/init/init-v2.js +53 -7
  14. package/dist/src/command-line/migrate/migrate.js +1 -0
  15. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.d.ts +2 -2
  16. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +18 -5
  17. package/dist/src/command-line/nx-cloud/connect/view-logs.js +1 -1
  18. package/dist/src/command-line/show/command-object.js +3 -3
  19. package/dist/src/command-line/show/show-target/index.d.ts +3 -0
  20. package/dist/src/command-line/show/show-target/index.js +9 -0
  21. package/dist/src/command-line/show/show-target/info.d.ts +27 -0
  22. package/dist/src/command-line/show/show-target/info.js +299 -0
  23. package/dist/src/command-line/show/show-target/inputs.d.ts +2 -0
  24. package/dist/src/command-line/show/show-target/inputs.js +186 -0
  25. package/dist/src/command-line/show/show-target/outputs.d.ts +2 -0
  26. package/dist/src/command-line/show/show-target/outputs.js +195 -0
  27. package/dist/src/command-line/show/show-target/utils.d.ts +26 -0
  28. package/dist/src/command-line/show/show-target/utils.js +185 -0
  29. package/dist/src/command-line/yargs-utils/shared-options.js +5 -1
  30. package/dist/src/config/nx-json.d.ts +3 -1
  31. package/dist/src/config/workspace-json-project-json.d.ts +2 -1
  32. package/dist/src/core/graph/main.js +1 -1
  33. package/dist/src/daemon/client/client.d.ts +11 -4
  34. package/dist/src/daemon/client/client.js +44 -48
  35. package/dist/src/daemon/client/daemon-environment.d.ts +4 -0
  36. package/dist/src/daemon/client/daemon-environment.js +119 -0
  37. package/dist/src/daemon/client/daemon-socket-messenger.d.ts +2 -5
  38. package/dist/src/daemon/client/daemon-socket-messenger.js +1 -1
  39. package/dist/src/daemon/message-types/daemon-message.d.ts +6 -0
  40. package/dist/src/daemon/message-types/daemon-message.js +6 -0
  41. package/dist/src/daemon/server/handle-hash-tasks.d.ts +1 -1
  42. package/dist/src/daemon/server/handle-hash-tasks.js +1 -1
  43. package/dist/src/daemon/server/handle-outputs-tracking.d.ts +4 -4
  44. package/dist/src/daemon/server/handle-outputs-tracking.js +11 -11
  45. package/dist/src/daemon/server/outputs-tracking.d.ts +18 -3
  46. package/dist/src/daemon/server/outputs-tracking.js +49 -22
  47. package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +2 -1
  48. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +20 -4
  49. package/dist/src/daemon/server/server.js +71 -40
  50. package/dist/src/executors/run-commands/running-tasks.js +2 -3
  51. package/dist/src/executors/run-script/run-script.impl.js +16 -8
  52. package/dist/src/hasher/hash-task.d.ts +9 -1
  53. package/dist/src/hasher/hash-task.js +42 -15
  54. package/dist/src/hasher/native-task-hasher-impl.d.ts +1 -1
  55. package/dist/src/hasher/native-task-hasher-impl.js +4 -6
  56. package/dist/src/hasher/task-hasher.d.ts +20 -9
  57. package/dist/src/hasher/task-hasher.js +34 -6
  58. package/dist/src/native/index.d.ts +34 -7
  59. package/dist/src/native/native-bindings.js +1 -1
  60. package/dist/src/native/nx.wasi-browser.js +0 -1
  61. package/dist/src/native/nx.wasi.cjs +0 -1
  62. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  63. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  64. package/dist/src/plugins/js/lock-file/npm-parser.js +15 -3
  65. package/dist/src/plugins/js/lock-file/utils/package-json.d.ts +1 -1
  66. package/dist/src/plugins/js/lock-file/utils/package-json.js +3 -1
  67. package/dist/src/plugins/js/utils/register.js +83 -4
  68. package/dist/src/project-graph/error-types.js +31 -11
  69. package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
  70. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +44 -33
  71. package/dist/src/project-graph/plugins/isolation/message-types.d.ts +1 -1
  72. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +9 -0
  73. package/dist/src/project-graph/plugins/isolation/messaging.js +2 -0
  74. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +44 -82
  75. package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +6 -0
  76. package/dist/src/tasks-runner/cache.d.ts +6 -0
  77. package/dist/src/tasks-runner/cache.js +58 -0
  78. package/dist/src/tasks-runner/init-tasks-runner.js +13 -7
  79. package/dist/src/tasks-runner/run-command.js +13 -5
  80. package/dist/src/tasks-runner/task-env.d.ts +6 -3
  81. package/dist/src/tasks-runner/task-env.js +23 -6
  82. package/dist/src/tasks-runner/task-orchestrator.d.ts +79 -7
  83. package/dist/src/tasks-runner/task-orchestrator.js +327 -120
  84. package/dist/src/tasks-runner/tasks-schedule.d.ts +5 -2
  85. package/dist/src/tasks-runner/tasks-schedule.js +31 -17
  86. package/dist/src/tasks-runner/utils.d.ts +3 -3
  87. package/dist/src/tasks-runner/utils.js +5 -6
  88. package/dist/src/utils/ab-testing.d.ts +14 -33
  89. package/dist/src/utils/ab-testing.js +6 -4
  90. package/dist/src/utils/dotenv.js +4 -6
  91. package/dist/src/utils/nx-cloud-utils.d.ts +1 -0
  92. package/dist/src/utils/nx-cloud-utils.js +5 -1
  93. package/dist/src/utils/package-json.js +16 -1
  94. package/dist/src/utils/wait-for-socket-connection.d.ts +15 -0
  95. package/dist/src/utils/wait-for-socket-connection.js +53 -0
  96. package/package.json +14 -14
  97. package/dist/src/command-line/release/utils/test/test-utils.d.ts +0 -20
  98. package/dist/src/command-line/release/utils/test/test-utils.js +0 -25
  99. package/dist/src/command-line/release/version/test-utils.d.ts +0 -102
  100. package/dist/src/command-line/release/version/test-utils.js +0 -417
  101. package/dist/src/command-line/show/target.d.ts +0 -4
  102. package/dist/src/command-line/show/target.js +0 -730
  103. package/dist/src/daemon/client/exec-is-server-available.d.ts +0 -1
  104. package/dist/src/daemon/client/exec-is-server-available.js +0 -11
  105. package/dist/src/daemon/client/generate-help-output.d.ts +0 -1
  106. package/dist/src/daemon/client/generate-help-output.js +0 -26
@@ -772,6 +772,31 @@
772
772
  },
773
773
  "required": ["dependentTasksOutputFiles"],
774
774
  "additionalProperties": false
775
+ },
776
+ {
777
+ "type": "object",
778
+ "properties": {
779
+ "json": {
780
+ "type": "string",
781
+ "description": "Path to a JSON file. Must start with {workspaceRoot} or {projectRoot}. Supports globs."
782
+ },
783
+ "fields": {
784
+ "type": "array",
785
+ "items": {
786
+ "type": "string"
787
+ },
788
+ "description": "Allowlist of fields to include in the hash. Supports dot notation for nested paths (e.g. 'compilerOptions.target')."
789
+ },
790
+ "excludeFields": {
791
+ "type": "array",
792
+ "items": {
793
+ "type": "string"
794
+ },
795
+ "description": "Denylist of fields to exclude from the hash. Supports dot notation for nested paths."
796
+ }
797
+ },
798
+ "required": ["json"],
799
+ "additionalProperties": false
775
800
  }
776
801
  ]
777
802
  }
@@ -322,6 +322,31 @@
322
322
  },
323
323
  "required": ["dependentTasksOutputFiles"],
324
324
  "additionalProperties": false
325
+ },
326
+ {
327
+ "type": "object",
328
+ "properties": {
329
+ "json": {
330
+ "type": "string",
331
+ "description": "Path to a JSON file. Must start with {workspaceRoot} or {projectRoot}. Supports globs."
332
+ },
333
+ "fields": {
334
+ "type": "array",
335
+ "items": {
336
+ "type": "string"
337
+ },
338
+ "description": "Allowlist of fields to include in the hash. Supports dot notation for nested paths (e.g. 'compilerOptions.target')."
339
+ },
340
+ "excludeFields": {
341
+ "type": "array",
342
+ "items": {
343
+ "type": "string"
344
+ },
345
+ "description": "Denylist of fields to exclude from the hash. Supports dot notation for nested paths."
346
+ }
347
+ },
348
+ "required": ["json"],
349
+ "additionalProperties": false
325
350
  }
326
351
  ]
327
352
  }
@@ -40,6 +40,15 @@ function getProjectGraph() {
40
40
  return (0, project_graph_1.createProjectGraphAsync)();
41
41
  }
42
42
  }
43
+ function getUndefinedDefaultsTransform(isAngularBuild) {
44
+ // `addUndefinedObjectDefaults` was introduced in @angular-devkit/core v20.
45
+ // `@nx/angular` supports Angular >=19, so fall back to `addUndefinedDefaults`
46
+ // when the object-specific transform is unavailable.
47
+ if (isAngularBuild && core_1.schema.transforms.addUndefinedObjectDefaults) {
48
+ return core_1.schema.transforms.addUndefinedObjectDefaults;
49
+ }
50
+ return core_1.schema.transforms.addUndefinedDefaults;
51
+ }
43
52
  async function createBuilderContext(builderInfo, context) {
44
53
  require('./compat');
45
54
  const fsHost = new NxScopedHostForBuilders(context.root, context.projectGraph);
@@ -51,12 +60,7 @@ async function createBuilderContext(builderInfo, context) {
51
60
  const registry = new core_1.schema.CoreSchemaRegistry();
52
61
  const isAngularBuild = builderInfo.builderName.startsWith('@angular/build:') ||
53
62
  ['@nx/angular:application', '@nx/angular:unit-test'].includes(builderInfo.builderName);
54
- if (isAngularBuild) {
55
- registry.addPostTransform(core_1.schema.transforms.addUndefinedObjectDefaults);
56
- }
57
- else {
58
- registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults);
59
- }
63
+ registry.addPostTransform(getUndefinedDefaultsTransform(isAngularBuild));
60
64
  registry.addSmartDefaultProvider('unparsed', () => {
61
65
  // This happens when context.scheduleTarget is used to run a target using nx:run-commands
62
66
  return [];
@@ -150,12 +154,7 @@ async function scheduleTarget(root, opts, verbose, projectGraph) {
150
154
  const isAngularBuild = builderName.startsWith('@angular/build:') ||
151
155
  ['@nx/angular:application', '@nx/angular:unit-test'].includes(builderName);
152
156
  const registry = new core_1.schema.CoreSchemaRegistry();
153
- if (isAngularBuild) {
154
- registry.addPostTransform(core_1.schema.transforms.addUndefinedObjectDefaults);
155
- }
156
- else {
157
- registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults);
158
- }
157
+ registry.addPostTransform(getUndefinedDefaultsTransform(isAngularBuild));
159
158
  registry.addSmartDefaultProvider('unparsed', () => {
160
159
  // This happens when context.scheduleTarget is used to run a target using nx:run-commands
161
160
  return [];
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.daemonHandler = daemonHandler;
4
+ const cache_1 = require("../../daemon/cache");
4
5
  const tmp_dir_1 = require("../../daemon/tmp-dir");
5
6
  const handle_import_1 = require("../../utils/handle-import");
6
7
  const output_1 = require("../../utils/output");
7
- const generate_help_output_1 = require("../../daemon/client/generate-help-output");
8
8
  async function daemonHandler(args) {
9
+ const { daemonClient } = await (0, handle_import_1.handleImport)('../../daemon/client/client.js', __dirname);
9
10
  if (args.start) {
10
- const { daemonClient } = await (0, handle_import_1.handleImport)('../../daemon/client/client.js', __dirname);
11
11
  const pid = await daemonClient.startInBackground();
12
12
  output_1.output.log({
13
13
  title: `Daemon Server - Started in a background process...`,
@@ -17,11 +17,15 @@ async function daemonHandler(args) {
17
17
  });
18
18
  }
19
19
  else if (args.stop) {
20
- const { daemonClient } = await (0, handle_import_1.handleImport)('../../daemon/client/client.js', __dirname);
21
20
  await daemonClient.stop();
22
21
  output_1.output.log({ title: 'Daemon Server - Stopped' });
23
22
  }
23
+ else if (await daemonClient.isServerAvailable()) {
24
+ const pid = (0, cache_1.getDaemonProcessIdSync)();
25
+ console.log(`Nx Daemon is currently running:
26
+ - Logs: ${tmp_dir_1.DAEMON_OUTPUT_LOG_FILE}${pid ? `\n - Process ID: ${pid}` : ''}`);
27
+ }
24
28
  else {
25
- console.log((0, generate_help_output_1.generateDaemonHelpOutput)());
29
+ console.log('Nx Daemon is not running.');
26
30
  }
27
31
  }
@@ -31,6 +31,7 @@ const nx_deps_cache_1 = require("../../project-graph/nx-deps-cache");
31
31
  const task_hasher_1 = require("../../hasher/task-hasher");
32
32
  const find_matching_projects_1 = require("../../utils/find-matching-projects");
33
33
  const create_task_hasher_1 = require("../../hasher/create-task-hasher");
34
+ const task_env_1 = require("../../tasks-runner/task-env");
34
35
  const error_types_1 = require("../../project-graph/error-types");
35
36
  const nx_cloud_utils_1 = require("../../utils/nx-cloud-utils");
36
37
  // maps file extention to MIME types
@@ -942,7 +943,13 @@ async function createJsonOutput(prunedGraph, rawGraph, projects, targets) {
942
943
  const taskGraph = (0, create_task_graph_1.createTaskGraph)(rawGraph, {}, projects, targets, undefined, {});
943
944
  const hasher = (0, create_task_hasher_1.createTaskHasher)(rawGraph, (0, configuration_1.readNxJson)());
944
945
  let tasks = Object.values(taskGraph.tasks);
945
- const hashes = await hasher.hashTasks(tasks, taskGraph);
946
+ // Match the runtime path: each task is hashed against its own env so
947
+ // the graph-view hash matches the hash used when the task actually runs.
948
+ const perTaskEnvs = {};
949
+ for (const task of tasks) {
950
+ perTaskEnvs[task.id] = (0, task_env_1.getTaskSpecificEnv)(task, rawGraph);
951
+ }
952
+ const hashes = await hasher.hashTasks(tasks, taskGraph, perTaskEnvs);
946
953
  response.tasks = taskGraph;
947
954
  response.taskPlans = tasks.reduce((acc, task, index) => {
948
955
  acc[task.id] = Object.keys(hashes[index].details.nodes).sort();
@@ -17,7 +17,7 @@ async function addNxToMonorepo(options, guided = true) {
17
17
  let targetDefaults;
18
18
  let cacheableOperations;
19
19
  let scriptOutputs = {};
20
- let useNxCloud;
20
+ let nxCloudChoice;
21
21
  if (options.interactive && scripts.length > 0 && guided) {
22
22
  output_1.output.log({
23
23
  title: '🧑‍🔧 Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration',
@@ -55,27 +55,37 @@ async function addNxToMonorepo(options, guided = true) {
55
55
  },
56
56
  ]))[scriptName];
57
57
  }
58
- useNxCloud =
59
- options.nxCloud ?? (await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)());
58
+ nxCloudChoice =
59
+ options.nxCloud === true
60
+ ? 'yes'
61
+ : options.nxCloud === false
62
+ ? 'skip'
63
+ : await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)();
60
64
  }
61
65
  else {
62
66
  targetDefaults = [];
63
67
  cacheableOperations = options.cacheable ?? [];
64
- useNxCloud =
65
- options.nxCloud ??
66
- (options.interactive
67
- ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
68
- : false);
68
+ nxCloudChoice =
69
+ options.nxCloud === true
70
+ ? 'yes'
71
+ : options.nxCloud === false
72
+ ? 'skip'
73
+ : options.interactive
74
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
75
+ : 'skip';
69
76
  }
70
77
  (0, utils_1.createNxJsonFile)(repoRoot, targetDefaults, cacheableOperations, scriptOutputs);
71
78
  (0, utils_1.updateGitIgnore)(repoRoot);
72
79
  (0, utils_1.addDepsToPackageJson)(repoRoot);
73
80
  output_1.output.log({ title: '📦 Installing dependencies' });
74
81
  (0, utils_1.runInstall)(repoRoot);
75
- if (useNxCloud) {
82
+ if (nxCloudChoice === 'yes') {
76
83
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
77
84
  await (0, utils_1.initCloud)('nx-init-monorepo');
78
85
  }
86
+ else if (nxCloudChoice === 'never') {
87
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
88
+ }
79
89
  }
80
90
  // scanning package.json files
81
91
  function allProjectPackageJsonFiles(repoRoot) {
@@ -41,7 +41,7 @@ async function addNxToNest(options, packageJson) {
41
41
  });
42
42
  let cacheableOperations;
43
43
  let scriptOutputs = {};
44
- let useNxCloud;
44
+ let nxCloudChoice;
45
45
  if (options.interactive && scripts.length > 0) {
46
46
  output_1.output.log({
47
47
  title: '🧑‍🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
@@ -67,16 +67,23 @@ async function addNxToNest(options, packageJson) {
67
67
  },
68
68
  ]))[scriptName];
69
69
  }
70
- useNxCloud =
71
- options.nxCloud ?? (await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)());
70
+ nxCloudChoice =
71
+ options.nxCloud === true
72
+ ? 'yes'
73
+ : options.nxCloud === false
74
+ ? 'skip'
75
+ : await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)();
72
76
  }
73
77
  else {
74
78
  cacheableOperations = options.cacheable ?? [];
75
- useNxCloud =
76
- options.nxCloud ??
77
- (options.interactive
78
- ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
79
- : false);
79
+ nxCloudChoice =
80
+ options.nxCloud === true
81
+ ? 'yes'
82
+ : options.nxCloud === false
83
+ ? 'skip'
84
+ : options.interactive
85
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
86
+ : 'skip';
80
87
  }
81
88
  (0, utils_1.createNxJsonFile)(repoRoot, [], [...cacheableOperations, ...nestCacheableScripts], scriptOutputs);
82
89
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
@@ -92,10 +99,13 @@ async function addNxToNest(options, packageJson) {
92
99
  }
93
100
  output_1.output.log({ title: '📦 Installing dependencies' });
94
101
  (0, utils_1.runInstall)(repoRoot);
95
- if (useNxCloud) {
102
+ if (nxCloudChoice === 'yes') {
96
103
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
97
104
  await (0, utils_1.initCloud)('nx-init-nest');
98
105
  }
106
+ else if (nxCloudChoice === 'never') {
107
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
108
+ }
99
109
  }
100
110
  function addNestPluginToPackageJson(repoRoot) {
101
111
  const path = (0, path_1.join)(repoRoot, `package.json`);
@@ -14,7 +14,7 @@ async function addNxToNpmRepo(options, guided = true) {
14
14
  output_1.output.log({ title: '🐳 Nx initialization' });
15
15
  let cacheableOperations;
16
16
  let scriptOutputs = {};
17
- let useNxCloud;
17
+ let nxCloudChoice;
18
18
  const packageJson = (0, fileutils_1.readJsonFile)('package.json');
19
19
  const scripts = Object.keys(packageJson.scripts ?? {}).filter((s) => !s.startsWith('pre') && !s.startsWith('post'));
20
20
  if (options.interactive && scripts.length > 0 && guided) {
@@ -43,16 +43,23 @@ async function addNxToNpmRepo(options, guided = true) {
43
43
  },
44
44
  ]))[scriptName];
45
45
  }
46
- useNxCloud =
47
- options.nxCloud ?? (await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)());
46
+ nxCloudChoice =
47
+ options.nxCloud === true
48
+ ? 'yes'
49
+ : options.nxCloud === false
50
+ ? 'skip'
51
+ : await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)();
48
52
  }
49
53
  else {
50
54
  cacheableOperations = options.cacheable ?? [];
51
- useNxCloud =
52
- options.nxCloud ??
53
- (options.interactive
54
- ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
55
- : false);
55
+ nxCloudChoice =
56
+ options.nxCloud === true
57
+ ? 'yes'
58
+ : options.nxCloud === false
59
+ ? 'skip'
60
+ : options.interactive
61
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
62
+ : 'skip';
56
63
  }
57
64
  (0, utils_1.createNxJsonFile)(repoRoot, [], cacheableOperations, scriptOutputs);
58
65
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
@@ -66,8 +73,11 @@ async function addNxToNpmRepo(options, guided = true) {
66
73
  }
67
74
  output_1.output.log({ title: '📦 Installing dependencies' });
68
75
  (0, utils_1.runInstall)(repoRoot, pmc);
69
- if (useNxCloud) {
76
+ if (nxCloudChoice === 'yes') {
70
77
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
71
78
  await (0, utils_1.initCloud)('nx-init-npm-repo');
72
79
  }
80
+ else if (nxCloudChoice === 'never') {
81
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
82
+ }
73
83
  }
@@ -37,16 +37,24 @@ async function addNxToAngularCliRepo(options) {
37
37
  const cacheableOperations = !options.integrated
38
38
  ? await collectCacheableOperations(options)
39
39
  : [];
40
- const useNxCloud = options.nxCloud ??
41
- (options.interactive ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)() : false);
40
+ const nxCloudChoice = options.nxCloud === true
41
+ ? 'yes'
42
+ : options.nxCloud === false
43
+ ? 'skip'
44
+ : options.interactive
45
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
46
+ : 'skip';
42
47
  output_1.output.log({ title: '📦 Installing dependencies' });
43
48
  installDependencies();
44
49
  output_1.output.log({ title: '📝 Setting up workspace' });
45
50
  await setupWorkspace(cacheableOperations, options.integrated);
46
- if (useNxCloud) {
51
+ if (nxCloudChoice === 'yes') {
47
52
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
48
53
  await (0, utils_1.initCloud)('nx-init-angular');
49
54
  }
55
+ else if (nxCloudChoice === 'never') {
56
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
57
+ }
50
58
  }
51
59
  async function collectCacheableOperations(options) {
52
60
  let cacheableOperations;
@@ -90,10 +90,13 @@ async function getLegacyMigrationFunctionIfApplicable(repoRoot, options) {
90
90
  }
91
91
  return async () => {
92
92
  output_1.output.log({ title: '🐳 Nx initialization' });
93
- const useNxCloud = options.nxCloud ??
94
- (options.interactive
95
- ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
96
- : false);
93
+ const nxCloudChoice = options.nxCloud === true
94
+ ? 'yes'
95
+ : options.nxCloud === false
96
+ ? 'skip'
97
+ : options.interactive
98
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
99
+ : 'skip';
97
100
  output_1.output.log({ title: '📦 Installing dependencies' });
98
101
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
99
102
  await installDependencies(repoRoot, {
@@ -107,10 +110,13 @@ async function getLegacyMigrationFunctionIfApplicable(repoRoot, options) {
107
110
  stdio: [0, 1, 2],
108
111
  windowsHide: true,
109
112
  });
110
- if (useNxCloud) {
113
+ if (nxCloudChoice === 'yes') {
111
114
  output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
112
115
  await (0, utils_1.initCloud)('nx-init-angular');
113
116
  }
117
+ else if (nxCloudChoice === 'never') {
118
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
119
+ }
114
120
  };
115
121
  }
116
122
  async function installDependencies(repoRoot, pkgInfo, pmc) {
@@ -9,6 +9,7 @@ export declare function addDepsToPackageJson(repoRoot: string, additionalPackage
9
9
  export declare function updateGitIgnore(root: string): void;
10
10
  export declare function runInstall(repoRoot: string, pmc?: PackageManagerCommands): void;
11
11
  export declare function initCloud(installationSource: 'nx-init' | 'nx-init-angular' | 'nx-init-monorepo' | 'nx-init-nest' | 'nx-init-npm-repo' | 'nx-init-turborepo'): Promise<void>;
12
+ export declare function setNeverConnectToCloud(repoRoot: string): void;
12
13
  export declare function addVsCodeRecommendedExtensions(repoRoot: string, extensions: string[]): void;
13
14
  export declare function markRootPackageJsonAsNxProjectLegacy(repoRoot: string, cacheableScripts: string[], pmc: PackageManagerCommands): void;
14
15
  export declare function markPackageJsonAsNxProject(packageJsonPath: string): void;
@@ -6,6 +6,7 @@ exports.addDepsToPackageJson = addDepsToPackageJson;
6
6
  exports.updateGitIgnore = updateGitIgnore;
7
7
  exports.runInstall = runInstall;
8
8
  exports.initCloud = initCloud;
9
+ exports.setNeverConnectToCloud = setNeverConnectToCloud;
9
10
  exports.addVsCodeRecommendedExtensions = addVsCodeRecommendedExtensions;
10
11
  exports.markRootPackageJsonAsNxProjectLegacy = markRootPackageJsonAsNxProjectLegacy;
11
12
  exports.markPackageJsonAsNxProject = markPackageJsonAsNxProject;
@@ -191,7 +192,7 @@ function updateGitIgnore(root) {
191
192
  }
192
193
  function runInstall(repoRoot, pmc = (0, package_manager_1.getPackageManagerCommand)()) {
193
194
  (0, child_process_1.execSync)(pmc.install, {
194
- stdio: [0, 1, 2],
195
+ stdio: ['ignore', 'ignore', 'inherit'],
195
196
  cwd: repoRoot,
196
197
  windowsHide: true,
197
198
  });
@@ -202,6 +203,12 @@ async function initCloud(installationSource) {
202
203
  });
203
204
  await (0, connect_to_nx_cloud_1.printSuccessMessage)(token, installationSource);
204
205
  }
206
+ function setNeverConnectToCloud(repoRoot) {
207
+ const nxJsonPath = (0, path_1.join)(repoRoot, 'nx.json');
208
+ const nxJson = (0, fileutils_1.readJsonFile)(nxJsonPath);
209
+ nxJson.neverConnectToCloud = true;
210
+ (0, fileutils_1.writeJsonFile)(nxJsonPath, nxJson);
211
+ }
205
212
  function addVsCodeRecommendedExtensions(repoRoot, extensions) {
206
213
  const vsCodeExtensionsPath = (0, path_1.join)(repoRoot, '.vscode/extensions.json');
207
214
  if ((0, fileutils_1.fileExists)(vsCodeExtensionsPath)) {
@@ -4,6 +4,7 @@ exports.initHandler = initHandler;
4
4
  exports.getPluginReason = getPluginReason;
5
5
  exports.detectPlugins = detectPlugins;
6
6
  const fs_1 = require("fs");
7
+ const path_1 = require("path");
7
8
  const enquirer_1 = require("enquirer");
8
9
  const semver_1 = require("semver");
9
10
  const nx_json_1 = require("../../config/nx-json");
@@ -102,6 +103,42 @@ async function initHandlerImpl(options) {
102
103
  });
103
104
  return;
104
105
  }
106
+ // When in an empty directory (no package.json) and the user hasn't explicitly
107
+ // chosen a setup method, prompt them to pick between .nx and package.json setup.
108
+ // Skip the prompt when stdin is not a TTY (e.g. CI, e2e tests) to avoid hangs.
109
+ if (!(0, fs_1.existsSync)('package.json') &&
110
+ !options.useDotNxInstallation &&
111
+ options.interactive &&
112
+ !aiMode &&
113
+ process.stdin.isTTY) {
114
+ const setupMode = await (0, enquirer_1.prompt)([
115
+ {
116
+ type: 'select',
117
+ name: 'setupMode',
118
+ message: 'How would you like to set up Nx in this directory?',
119
+ choices: [
120
+ {
121
+ name: '.nx installation (recommended for non-JavaScript projects)',
122
+ },
123
+ {
124
+ name: 'package.json installation (recommended for JavaScript/TypeScript projects)',
125
+ },
126
+ ],
127
+ },
128
+ ]).then((r) => r.setupMode);
129
+ if (setupMode.startsWith('package.json')) {
130
+ // Create a minimal package.json so the JS/TS workflow takes over
131
+ const workspaceName = (0, path_1.basename)(process.cwd());
132
+ (0, fileutils_1.writeJsonFile)('package.json', {
133
+ name: workspaceName,
134
+ version: '0.0.0',
135
+ private: true,
136
+ });
137
+ }
138
+ else {
139
+ options.useDotNxInstallation = true;
140
+ }
141
+ }
105
142
  const _isNonJs = !(0, fs_1.existsSync)('package.json') || options.useDotNxInstallation;
106
143
  const packageJson = _isNonJs
107
144
  ? null
@@ -251,22 +288,31 @@ async function initHandlerImpl(options) {
251
288
  results.errors.forEach((e) => output_1.output.error(e));
252
289
  }
253
290
  }
254
- let useNxCloud = options.nxCloud;
255
- if (useNxCloud === undefined) {
256
- output_1.output.log({ title: '🛠️ Setting up Self-Healing CI and Remote Caching' });
257
- useNxCloud = options.interactive
291
+ let nxCloudChoice;
292
+ if (options.nxCloud === true) {
293
+ nxCloudChoice = 'yes';
294
+ }
295
+ else if (options.nxCloud === false) {
296
+ nxCloudChoice = 'skip';
297
+ }
298
+ else {
299
+ nxCloudChoice = options.interactive
258
300
  ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
259
- : false;
301
+ : 'skip';
260
302
  }
261
- if (useNxCloud) {
303
+ if (nxCloudChoice === 'yes') {
262
304
  await (0, utils_1.initCloud)('nx-init');
263
305
  }
306
+ else if (nxCloudChoice === 'never') {
307
+ (0, utils_1.setNeverConnectToCloud)(repoRoot);
308
+ }
264
309
  await (0, ab_testing_1.recordStat)({
265
310
  command: 'init',
266
311
  nxVersion: version,
267
- useCloud: !!useNxCloud,
312
+ useCloud: nxCloudChoice === 'yes',
268
313
  meta: {
269
314
  type: 'complete',
315
+ nxCloudArg: nxCloudChoice,
270
316
  nodeVersion: process.versions.node,
271
317
  os: process.platform,
272
318
  packageManager: (0, package_manager_2.detectPackageManager)(),
@@ -949,6 +949,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts) {
949
949
  ['nx', '@nrwl/workspace'].includes(opts.targetPackage) &&
950
950
  (await isMigratingToNewMajor(from, opts.targetVersion)) &&
951
951
  !(0, is_ci_1.isCI)() &&
952
+ !(0, nx_cloud_utils_1.isNxCloudDisabled)(originalNxJson) &&
952
953
  !(0, nx_cloud_utils_1.isNxCloudUsed)(originalNxJson)) {
953
954
  output_1.output.success({
954
955
  title: 'Connect to Nx Cloud',
@@ -1,7 +1,7 @@
1
1
  import { ConnectToNxCloudOptions } from '../../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
2
2
  import { NxJsonConfiguration } from '../../../config/nx-json';
3
3
  import { NxArgs } from '../../../utils/command-line-utils';
4
- import { MessageKey } from '../../../utils/ab-testing';
4
+ import { MessageKey, MessageOptionKey } from '../../../utils/ab-testing';
5
5
  export declare function onlyDefaultRunnerIsUsed(nxJson: NxJsonConfiguration): boolean;
6
6
  export declare function connectToNxCloudIfExplicitlyAsked(opts: NxArgs): Promise<void>;
7
7
  export declare function connectWorkspaceToCloud(options: ConnectToNxCloudOptions, directory?: string): Promise<string>;
@@ -9,5 +9,5 @@ export declare function connectToNxCloudCommand(options: {
9
9
  generateToken?: boolean;
10
10
  checkRemote?: boolean;
11
11
  }, command?: string): Promise<boolean>;
12
- export declare function connectExistingRepoToNxCloudPrompt(command?: string, key?: MessageKey): Promise<boolean>;
12
+ export declare function connectExistingRepoToNxCloudPrompt(command?: string, key?: MessageKey): Promise<MessageOptionKey>;
13
13
  export declare function connectToNxCloudWithPrompt(command: string): Promise<void>;
@@ -7,6 +7,7 @@ exports.connectToNxCloudCommand = connectToNxCloudCommand;
7
7
  exports.connectExistingRepoToNxCloudPrompt = connectExistingRepoToNxCloudPrompt;
8
8
  exports.connectToNxCloudWithPrompt = connectToNxCloudWithPrompt;
9
9
  const tslib_1 = require("tslib");
10
+ const path_1 = require("path");
10
11
  const handle_import_1 = require("../../../utils/handle-import");
11
12
  const output_1 = require("../../../utils/output");
12
13
  const configuration_1 = require("../../../config/configuration");
@@ -14,6 +15,7 @@ const tree_1 = require("../../../generators/tree");
14
15
  const connect_to_nx_cloud_1 = require("../../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud");
15
16
  const url_shorten_1 = require("../../../nx-cloud/utilities/url-shorten");
16
17
  const nx_cloud_utils_1 = require("../../../utils/nx-cloud-utils");
18
+ const fileutils_1 = require("../../../utils/fileutils");
17
19
  const child_process_1 = require("../../../utils/child-process");
18
20
  const ab_testing_1 = require("../../../utils/ab-testing");
19
21
  const versions_1 = require("../../../utils/versions");
@@ -124,14 +126,15 @@ function sleep(ms) {
124
126
  return new Promise((resolve) => setTimeout(resolve, ms));
125
127
  }
126
128
  async function connectExistingRepoToNxCloudPrompt(command = 'init', key = 'setupNxCloud') {
127
- const res = await nxCloudPrompt(key).then((value) => value === 'yes');
129
+ const res = await nxCloudPrompt(key);
128
130
  await (0, ab_testing_1.recordStat)({
129
131
  command,
130
132
  nxVersion: versions_1.nxVersion,
131
- useCloud: res,
133
+ useCloud: res === 'yes',
132
134
  meta: {
133
135
  type: 'complete',
134
136
  setupCloudPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage(key) || '',
137
+ nxCloudArg: res,
135
138
  nodeVersion: process.versions.node,
136
139
  os: process.platform,
137
140
  packageManager: (0, package_manager_1.detectPackageManager)(),
@@ -143,9 +146,18 @@ async function connectExistingRepoToNxCloudPrompt(command = 'init', key = 'setup
143
146
  }
144
147
  async function connectToNxCloudWithPrompt(command) {
145
148
  const setNxCloud = await nxCloudPrompt('setupNxCloud');
146
- const useCloud = setNxCloud === 'yes'
147
- ? await connectToNxCloudCommand({ generateToken: false }, command)
148
- : false;
149
+ let useCloud = false;
150
+ if (setNxCloud === 'yes') {
151
+ useCloud = await connectToNxCloudCommand({ generateToken: false }, command);
152
+ }
153
+ else if (setNxCloud === 'never') {
154
+ const nxJsonPath = (0, path_1.join)(workspace_root_1.workspaceRoot, 'nx.json');
155
+ const nxJson = (0, configuration_1.readNxJson)();
156
+ if (nxJson) {
157
+ nxJson.neverConnectToCloud = true;
158
+ (0, fileutils_1.writeJsonFile)(nxJsonPath, nxJson);
159
+ }
160
+ }
149
161
  await (0, ab_testing_1.recordStat)({
150
162
  command,
151
163
  nxVersion: versions_1.nxVersion,
@@ -153,6 +165,7 @@ async function connectToNxCloudWithPrompt(command) {
153
165
  meta: {
154
166
  type: 'complete',
155
167
  setupCloudPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage('setupNxCloud') || '',
168
+ nxCloudArg: setNxCloud,
156
169
  nodeVersion: process.versions.node,
157
170
  os: process.platform,
158
171
  packageManager: (0, package_manager_1.detectPackageManager)(),
@@ -19,7 +19,7 @@ async function viewLogs() {
19
19
  return 1;
20
20
  }
21
21
  const setupNxCloud = await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)('view-logs', 'setupViewLogs');
22
- if (!setupNxCloud) {
22
+ if (setupNxCloud !== 'yes') {
23
23
  return;
24
24
  }
25
25
  try {
@@ -154,7 +154,7 @@ const showTargetInfoCommand = {
154
154
  .example('$0 show target my-app:build -c production', 'Show target configuration with production configuration applied'),
155
155
  handler: async (args) => {
156
156
  const exitCode = await (0, handle_errors_1.handleErrors)(args.verbose, async () => {
157
- const { showTargetInfoHandler, showTargetInputsHandler, showTargetOutputsHandler, } = await (0, handle_import_1.handleImport)('./target.js', __dirname);
157
+ const { showTargetInfoHandler, showTargetInputsHandler, showTargetOutputsHandler, } = await (0, handle_import_1.handleImport)('./show-target/index.js', __dirname);
158
158
  if (args.subcommand === 'inputs') {
159
159
  await showTargetInputsHandler(args);
160
160
  return;
@@ -187,7 +187,7 @@ const showTargetInputsCommand = {
187
187
  .example('$0 show target inputs my-app:build --check src/main.ts', 'Check if src/main.ts is an input for my-app:build'),
188
188
  handler: async (args) => {
189
189
  const exitCode = await (0, handle_errors_1.handleErrors)(args.verbose, async () => {
190
- const { showTargetInputsHandler } = await (0, handle_import_1.handleImport)('./target.js', __dirname);
190
+ const { showTargetInputsHandler } = await (0, handle_import_1.handleImport)('./show-target/index.js', __dirname);
191
191
  await showTargetInputsHandler(args);
192
192
  });
193
193
  process.exit(process.exitCode || exitCode);
@@ -217,7 +217,7 @@ const showTargetOutputsCommand = {
217
217
  .example('$0 show target outputs my-app:build --check dist/my-app', 'Check if dist/my-app is an output of my-app:build'),
218
218
  handler: async (args) => {
219
219
  const exitCode = await (0, handle_errors_1.handleErrors)(args.verbose, async () => {
220
- const { showTargetOutputsHandler } = await (0, handle_import_1.handleImport)('./target.js', __dirname);
220
+ const { showTargetOutputsHandler } = await (0, handle_import_1.handleImport)('./show-target/index.js', __dirname);
221
221
  await showTargetOutputsHandler(args);
222
222
  });
223
223
  process.exit(process.exitCode || exitCode);