nx 23.0.1 → 23.0.2

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 (48) hide show
  1. package/dist/bin/init-local.js +1 -1
  2. package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.d.ts +1 -0
  3. package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +6 -1
  4. package/dist/src/command-line/init/init-v2.js +1 -1
  5. package/dist/src/command-line/migrate/migrate.d.ts +2 -0
  6. package/dist/src/command-line/migrate/migrate.js +32 -6
  7. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.d.ts +1 -1
  8. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +28 -21
  9. package/dist/src/command-line/release/version/resolve-current-version.js +4 -1
  10. package/dist/src/core/graph/main.js +1 -1
  11. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +30 -11
  12. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  13. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  14. package/dist/src/plugins/js/lock-file/bun-parser.js +61 -38
  15. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +1 -3
  16. package/dist/src/plugins/js/package-json/create-package-json.js +22 -1
  17. package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +7 -0
  18. package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +26 -1
  19. package/dist/src/plugins/js/utils/register.d.ts +31 -10
  20. package/dist/src/plugins/js/utils/register.js +87 -18
  21. package/dist/src/plugins/package-json/create-nodes.js +5 -3
  22. package/dist/src/project-graph/operators.d.ts +0 -1
  23. package/dist/src/project-graph/operators.js +0 -44
  24. package/dist/src/project-graph/project-graph-builder.js +26 -10
  25. package/dist/src/project-graph/utils/project-configuration/target-defaults.js +23 -6
  26. package/dist/src/project-graph/utils/project-configuration-utils.js +28 -28
  27. package/dist/src/tasks-runner/batch/run-batch.js +3 -0
  28. package/dist/src/tasks-runner/cache.js +6 -0
  29. package/dist/src/tasks-runner/pseudo-terminal.d.ts +1 -0
  30. package/dist/src/tasks-runner/pseudo-terminal.js +18 -4
  31. package/dist/src/tasks-runner/run-command.js +24 -8
  32. package/dist/src/tasks-runner/utils.d.ts +1 -0
  33. package/dist/src/tasks-runner/utils.js +4 -0
  34. package/dist/src/utils/ab-testing.d.ts +4 -4
  35. package/dist/src/utils/ab-testing.js +5 -5
  36. package/dist/src/utils/catalog/manager-utils.d.ts +9 -0
  37. package/dist/src/utils/catalog/manager-utils.js +215 -0
  38. package/dist/src/utils/catalog/pnpm-manager.js +4 -102
  39. package/dist/src/utils/catalog/yarn-manager.js +4 -102
  40. package/dist/src/utils/is-sandbox.js +2 -0
  41. package/dist/src/utils/min-release-age/behavior/pnpm.d.ts +6 -5
  42. package/dist/src/utils/min-release-age/behavior/pnpm.js +87 -339
  43. package/dist/src/utils/package-json.d.ts +1 -0
  44. package/dist/src/utils/package-manager.d.ts +6 -3
  45. package/dist/src/utils/package-manager.js +21 -7
  46. package/dist/src/utils/spinner.d.ts +13 -1
  47. package/dist/src/utils/spinner.js +20 -4
  48. package/package.json +16 -12
@@ -162,7 +162,7 @@ function handleAngularCLIFallbacks(workspace) {
162
162
  console.log(`- fix migrations that "almost work"`);
163
163
  console.log(`- commit a partially migrated state`);
164
164
  console.log(`- change versions of packages to match organizational requirements`);
165
- console.log(`And, in general, it is lot more reliable for non-trivial workspaces. Read more at: https://nx.dev/getting-started/nx-and-angular#ng-update-and-nx-migrate`);
165
+ console.log(`And, in general, it is lot more reliable for non-trivial workspaces. Read more at: https://nx.dev/docs/technologies/angular/guides/nx-and-angular#ng-update-vs-nx-migrate`);
166
166
  console.log(`Run "nx migrate latest" to update to the latest version of Nx.`);
167
167
  console.log(`Running "ng update" can still be useful in some dev workflows, so we aren't planning to remove it.`);
168
168
  console.log(`If you need to use it, run "FORCE_NG_UPDATE=true ng update".`);
@@ -1,5 +1,6 @@
1
1
  import { Tree } from '../../../../generators/tree';
2
2
  export declare const nxWrapperPath: (p?: typeof import("path")) => string;
3
+ export declare function getDotNxWrapperVersionCommand(platform?: NodeJS.Platform): string;
3
4
  export declare function generateDotNxSetup(version?: string): void;
4
5
  export declare function normalizeVersionForNxJson(pkg: string, version: string): string;
5
6
  export declare function writeMinimalNxJson(host: Tree, version: string): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.nxWrapperPath = void 0;
4
+ exports.getDotNxWrapperVersionCommand = getDotNxWrapperVersionCommand;
4
5
  exports.generateDotNxSetup = generateDotNxSetup;
5
6
  exports.normalizeVersionForNxJson = normalizeVersionForNxJson;
6
7
  exports.writeMinimalNxJson = writeMinimalNxJson;
@@ -50,6 +51,10 @@ const SHELL_SCRIPT_CONTENTS = [
50
51
  // Executes the nx wrapper script
51
52
  `node ${path.posix.join('$path_to_root', (0, exports.nxWrapperPath)(path.posix))} "$@"`,
52
53
  ].join('\n');
54
+ // cmd.exe can't run the bash './nx' wrapper; use the generated nx.bat on Windows.
55
+ function getDotNxWrapperVersionCommand(platform = process.platform) {
56
+ return platform === 'win32' ? '.\\nx.bat --version' : './nx --version';
57
+ }
53
58
  function generateDotNxSetup(version) {
54
59
  const host = new tree_1.FsTree(process.cwd(), false, '.nx setup');
55
60
  writeMinimalNxJson(host, version);
@@ -66,7 +71,7 @@ function generateDotNxSetup(version) {
66
71
  // This is needed when using a global nx with dot-nx, otherwise running any nx command using global command will fail due to missing modules.
67
72
  // Pipe stderr so failures surface in telemetry instead of bare "Command failed: ./nx --version".
68
73
  try {
69
- (0, child_process_1.execSync)('./nx --version', {
74
+ (0, child_process_1.execSync)(getDotNxWrapperVersionCommand(), {
70
75
  stdio: ['ignore', 'ignore', 'pipe'],
71
76
  encoding: 'utf8',
72
77
  windowsHide: true,
@@ -348,7 +348,7 @@ async function runInit(options, baseMeta) {
348
348
  }
349
349
  else {
350
350
  nxCloudChoice = options.interactive
351
- ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
351
+ ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)('init', 'setupNxCloud', false)
352
352
  : 'skip';
353
353
  }
354
354
  if (nxCloudChoice === 'yes') {
@@ -85,6 +85,7 @@ export declare class Migrator {
85
85
  }>;
86
86
  private createMigrateJson;
87
87
  private buildPackageJsonUpdates;
88
+ private resolveVersionForCascade;
88
89
  private populatePackageJsonUpdatesAndGetPackagesToCheck;
89
90
  private getPackageJsonUpdatesFromMigrationConfig;
90
91
  /**
@@ -172,6 +173,7 @@ export declare function createFetcher(pmc: PackageManagerCommands): ((pkg: strin
172
173
  stats?: MigrateFetchStats;
173
174
  };
174
175
  export { filterDowngradedUpdates };
176
+ export declare function generateMigrationsJsonAndUpdatePackageJson(root: string, opts: GenerateMigrations, fetch?: MigratorOptions['fetch']): Promise<void>;
175
177
  /**
176
178
  * Detects npm peer-dependency resolution failures. Keyed on the `ERESOLVE`
177
179
  * error code, which npm consistently emits for this class of failure across
@@ -6,6 +6,7 @@ exports.resolveCanonicalNxPackage = resolveCanonicalNxPackage;
6
6
  exports.resolveInclude = resolveInclude;
7
7
  exports.parseMigrationsOptions = parseMigrationsOptions;
8
8
  exports.createFetcher = createFetcher;
9
+ exports.generateMigrationsJsonAndUpdatePackageJson = generateMigrationsJsonAndUpdatePackageJson;
9
10
  exports.isNpmPeerDepsError = isNpmPeerDepsError;
10
11
  exports.resolveAgenticRunId = resolveAgenticRunId;
11
12
  exports.formatSkippedPromptsNextStep = formatSkippedPromptsNextStep;
@@ -191,16 +192,37 @@ class Migrator {
191
192
  !this.areIncompatiblePackagesPresent(packageUpdate.incompatibleWith) &&
192
193
  (!this.interactive ||
193
194
  (await this.runPackageJsonUpdatesConfirmationPrompt(packageUpdate, packageUpdateKey, packageToCheck.package)))) {
194
- Object.entries(packageUpdate.packages).forEach(([name, update]) => {
195
+ const updateEntries = Object.entries(packageUpdate.packages);
196
+ // Validate all up front so invalid metadata fails fast, before any
197
+ // resolution does I/O.
198
+ for (const [name, update] of updateEntries) {
195
199
  this.validatePackageUpdateVersion(packageToCheck.package, name, update);
196
- filteredUpdates[name] = update;
197
- this.packageUpdates[name] = update;
198
- });
200
+ }
201
+ // Resolve serially: resolution can prompt (pnpm strict cooldown) and
202
+ // append to minimumReleaseAgeExclude, so a serial loop avoids
203
+ // overlapping prompts and keeps packageUpdates ordering stable.
204
+ for (const [name, update] of updateEntries) {
205
+ const resolvedUpdate = {
206
+ ...update,
207
+ version: await this.resolveVersionForCascade(name, update.version),
208
+ };
209
+ filteredUpdates[name] = resolvedUpdate;
210
+ this.packageUpdates[name] = resolvedUpdate;
211
+ }
199
212
  }
200
213
  }
201
214
  await Promise.all(Object.entries(filteredUpdates).map(([name, update]) => this.buildPackageJsonUpdates(name, update)));
202
215
  }
203
216
  }
217
+ async resolveVersionForCascade(packageName, version) {
218
+ // Already a fully-qualified semver (incl. prereleases) - nothing to resolve.
219
+ if ((0, semver_1.valid)(version)) {
220
+ return version;
221
+ }
222
+ // Otherwise resolve the spec (range/tag) through the min-release-age policy,
223
+ // which also honors any configured minimumReleaseAgeExclude entries.
224
+ return (0, resolve_package_version_1.resolvePackageVersionRespectingMinReleaseAge)(packageName, version);
225
+ }
204
226
  async populatePackageJsonUpdatesAndGetPackagesToCheck(targetPackage, target) {
205
227
  let targetVersion = target.version;
206
228
  if (this.to[targetPackage]) {
@@ -1347,6 +1369,7 @@ function readNxVersion(packageJson, root) {
1347
1369
  (0, package_json_1.getDependencyVersionFromPackageJson)('@nx/workspace', root, packageJson) ??
1348
1370
  (0, package_json_1.getDependencyVersionFromPackageJson)('@nrwl/workspace', root, packageJson));
1349
1371
  }
1372
+ // Exported for testing the optional-include orchestration seam (see NXC-4590).
1350
1373
  async function generateMigrationsJsonAndUpdatePackageJson(root, opts, fetch) {
1351
1374
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
1352
1375
  let phase = 'fetch_migrations';
@@ -1417,7 +1440,11 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts, fetch) {
1417
1440
  const writableUpdates = (0, update_filters_1.filterDowngradedUpdates)(packageUpdates, (0, catalog_1.resolveCatalogSpecifiers)(originalPackageJson), installedPackageVersions);
1418
1441
  const wrotePackageJson = await updatePackageJson(root, writableUpdates);
1419
1442
  const wroteNxJsonInstallation = await updateInstallationDetails(root, writableUpdates);
1420
- const promptMigrationFiles = (0, prompt_files_1.writePromptMigrationFiles)(root, migrations, promptContents ?? {}, packageUpdates[walkedTargetPackage].version);
1443
+ // Under `--include=optional` the target's own entry is filtered out of
1444
+ // `packageUpdates` (it's a required package), so resolve the version
1445
+ // defensively. Also reused by the completion analytics below.
1446
+ const resolvedTargetVersion = packageUpdates[walkedTargetPackage]?.version ?? opts.targetVersion;
1447
+ const promptMigrationFiles = (0, prompt_files_1.writePromptMigrationFiles)(root, migrations, promptContents ?? {}, resolvedTargetVersion);
1421
1448
  if (migrations.length > 0) {
1422
1449
  await createMigrationsFile(root, [
1423
1450
  ...addSplitConfigurationMigrationIfAvailable(from, writableUpdates),
@@ -1429,7 +1456,6 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts, fetch) {
1429
1456
  : include === 'optional'
1430
1457
  ? `- Processed optional dependency updates only (skipped required package updates).`
1431
1458
  : null;
1432
- const resolvedTargetVersion = packageUpdates[walkedTargetPackage]?.version ?? opts.targetVersion;
1433
1459
  // The param expressions below evaluate before the report function is
1434
1460
  // entered; `safeReport` keeps them inside the analytics boundary so a
1435
1461
  // param-building throw can't surface here and convert an already
@@ -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<MessageOptionKey>;
12
+ export declare function connectExistingRepoToNxCloudPrompt(command?: string, key?: MessageKey, recordCompletion?: boolean): Promise<MessageOptionKey>;
13
13
  export declare function connectToNxCloudWithPrompt(command: string): Promise<void>;
@@ -180,27 +180,34 @@ async function runConnectToNxCloud(options, command) {
180
180
  function sleep(ms) {
181
181
  return new Promise((resolve) => setTimeout(resolve, ms));
182
182
  }
183
- async function connectExistingRepoToNxCloudPrompt(command = 'init', key = 'setupNxCloud') {
184
- const res = await nxCloudPrompt(key, utmMediumForCommand(command));
185
- await (0, ab_testing_1.recordStat)({
186
- command,
187
- nxVersion: versions_1.nxVersion,
188
- useCloud: res === 'yes',
189
- meta: {
190
- type: 'complete',
191
- setupCloudPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage(key) || '',
192
- nxCloudArg: res,
193
- nodeVersion: process.versions.node,
194
- os: process.platform,
195
- packageManager: (0, package_manager_1.detectPackageManager)(),
196
- aiAgent: (0, native_1.isAiAgent)(),
197
- isCI: (0, is_ci_1.isCI)(),
198
- },
199
- });
183
+ async function connectExistingRepoToNxCloudPrompt(command = 'init', key = 'setupNxCloud', recordCompletion = true) {
184
+ const res = await nxCloudPrompt(key, utmContentForCommand(command));
185
+ // TODO: once legacy init-v1 (the NX_ADD_PLUGINS=false / useInferencePlugins:false path) is
186
+ // removed, drop this recordStat and the recordCompletion flag entirely - init-v2 records its
187
+ // own complete, and view-logs should record its own stat, so this shared helper won't record.
188
+ // init-v2 records its own init "complete" stat, so it opts out here to avoid double-counting.
189
+ // Other callers (e.g. view-logs, legacy init-v1) rely on this as their only completion event.
190
+ if (recordCompletion) {
191
+ await (0, ab_testing_1.recordStat)({
192
+ command,
193
+ nxVersion: versions_1.nxVersion,
194
+ useCloud: res === 'yes',
195
+ meta: {
196
+ type: 'complete',
197
+ setupCloudPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage(key) || '',
198
+ nxCloudArg: res,
199
+ nodeVersion: process.versions.node,
200
+ os: process.platform,
201
+ packageManager: (0, package_manager_1.detectPackageManager)(),
202
+ aiAgent: (0, native_1.isAiAgent)(),
203
+ isCI: (0, is_ci_1.isCI)(),
204
+ },
205
+ });
206
+ }
200
207
  return res;
201
208
  }
202
209
  async function connectToNxCloudWithPrompt(command) {
203
- const setNxCloud = await nxCloudPrompt('setupNxCloud', utmMediumForCommand(command));
210
+ const setNxCloud = await nxCloudPrompt('setupNxCloud', utmContentForCommand(command));
204
211
  let useCloud = false;
205
212
  if (setNxCloud === 'yes') {
206
213
  useCloud = await connectToNxCloudCommand({ generateToken: false }, command);
@@ -229,7 +236,7 @@ async function connectToNxCloudWithPrompt(command) {
229
236
  },
230
237
  });
231
238
  }
232
- function utmMediumForCommand(command) {
239
+ function utmContentForCommand(command) {
233
240
  switch (command) {
234
241
  case 'migrate':
235
242
  return 'nx-migrate';
@@ -239,7 +246,7 @@ function utmMediumForCommand(command) {
239
246
  return 'nx-init';
240
247
  }
241
248
  }
242
- async function nxCloudPrompt(key, utmMedium) {
249
+ async function nxCloudPrompt(key, utmContent) {
243
250
  const { message, choices, initial, footer, hint } = ab_testing_1.messages.getPrompt(key);
244
251
  const promptConfig = {
245
252
  name: 'NxCloud',
@@ -249,7 +256,7 @@ async function nxCloudPrompt(key, utmMedium) {
249
256
  initial,
250
257
  }; // meeroslav: types in enquirer are not up to date
251
258
  if (footer) {
252
- promptConfig.footer = () => pc.dim(`${footer} ${(0, ab_testing_1.nxCloudHyperlink)(utmMedium)}`);
259
+ promptConfig.footer = () => pc.dim(`${footer} ${(0, ab_testing_1.nxCloudHyperlink)(utmContent)}`);
253
260
  }
254
261
  if (hint) {
255
262
  promptConfig.hint = () => pc.dim(hint);
@@ -67,7 +67,10 @@ async function resolveCurrentVersionFromRegistry(tree, projectGraphNode, release
67
67
  return cached.currentVersion;
68
68
  }
69
69
  let registryTxt = '';
70
- const spinner = spinner_1.globalSpinner.start(`Resolving the current version for ${projectGraphNode.name} from the configured registry...`);
70
+ // Skip non-TTY logging the resolved version is reported through the
71
+ // project's batched `ProjectLogger` so the spinner step shouldn't emit an
72
+ // out-of-band line that would bypass the grouped output.
73
+ const spinner = spinner_1.globalSpinner.start(`Resolving the current version for ${projectGraphNode.name} from the configured registry...`, undefined, { skipNonTtyLogging: true });
71
74
  try {
72
75
  const res = await versionActions.readCurrentVersionFromRegistry(tree, finalConfigForProject.currentVersionResolverMetadata);
73
76
  if (!res) {