nx 23.0.0 → 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.
- package/README.md +1 -2
- package/dist/bin/init-local.js +1 -1
- package/dist/release/changelog-renderer/index.d.ts +1 -0
- package/dist/release/changelog-renderer/index.js +27 -12
- package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.d.ts +1 -0
- package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +6 -1
- package/dist/src/command-line/init/init-v2.js +1 -1
- package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +3 -2
- package/dist/src/command-line/migrate/migrate.d.ts +2 -0
- package/dist/src/command-line/migrate/migrate.js +34 -7
- package/dist/src/command-line/migrate/resolve-package-version.js +3 -25
- package/dist/src/command-line/migrate/update-filters.js +2 -1
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.d.ts +1 -1
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +37 -20
- package/dist/src/command-line/release/version/resolve-current-version.js +4 -1
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/daemon/server/project-graph-incremental-recomputation.js +30 -11
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/plugins/js/lock-file/bun-parser.js +61 -38
- package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +1 -3
- package/dist/src/plugins/js/package-json/create-package-json.js +22 -1
- package/dist/src/plugins/js/project-graph/affected/tsconfig-json-changes.js +1 -1
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +7 -0
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +26 -1
- package/dist/src/plugins/js/utils/register.d.ts +31 -10
- package/dist/src/plugins/js/utils/register.js +87 -18
- package/dist/src/plugins/package-json/create-nodes.js +5 -3
- package/dist/src/project-graph/operators.d.ts +0 -1
- package/dist/src/project-graph/operators.js +0 -44
- package/dist/src/project-graph/project-graph-builder.js +26 -10
- package/dist/src/project-graph/utils/project-configuration/target-defaults.js +23 -6
- package/dist/src/project-graph/utils/project-configuration-utils.js +28 -28
- package/dist/src/tasks-runner/batch/run-batch.js +3 -0
- package/dist/src/tasks-runner/cache.js +6 -0
- package/dist/src/tasks-runner/pseudo-terminal.d.ts +1 -0
- package/dist/src/tasks-runner/pseudo-terminal.js +18 -4
- package/dist/src/tasks-runner/run-command.js +24 -8
- package/dist/src/tasks-runner/utils.d.ts +1 -0
- package/dist/src/tasks-runner/utils.js +4 -0
- package/dist/src/utils/ab-testing.d.ts +9 -0
- package/dist/src/utils/ab-testing.js +18 -4
- package/dist/src/utils/catalog/index.d.ts +7 -0
- package/dist/src/utils/catalog/index.js +31 -0
- package/dist/src/utils/catalog/manager-utils.d.ts +9 -0
- package/dist/src/utils/catalog/manager-utils.js +215 -0
- package/dist/src/utils/catalog/pnpm-manager.js +4 -102
- package/dist/src/utils/catalog/yarn-manager.js +4 -102
- package/dist/src/utils/is-sandbox.js +2 -0
- package/dist/src/utils/min-release-age/behavior/pnpm.d.ts +6 -5
- package/dist/src/utils/min-release-age/behavior/pnpm.js +87 -339
- package/dist/src/utils/package-json.d.ts +1 -0
- package/dist/src/utils/package-manager.d.ts +6 -3
- package/dist/src/utils/package-manager.js +21 -7
- package/dist/src/utils/spinner.d.ts +13 -1
- package/dist/src/utils/spinner.js +20 -4
- package/dist/src/utils/terminal-link.d.ts +16 -0
- package/dist/src/utils/terminal-link.js +87 -0
- package/package.json +19 -15
package/README.md
CHANGED
|
@@ -7,13 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
<div style="text-align: center;">
|
|
9
9
|
|
|
10
|
-
[](https://circleci.com/gh/nrwl/nx)
|
|
11
10
|
[]()
|
|
12
11
|
[](https://www.npmjs.com/package/nx)
|
|
13
12
|
[]()
|
|
14
13
|
[](http://commitizen.github.io/cz-cli/)
|
|
15
|
-
[](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
16
14
|
[](https://go.nx.dev/community)
|
|
15
|
+
[](https://nx.dev/docs/features/ci-features/sandboxing)
|
|
17
16
|
|
|
18
17
|
</div>
|
|
19
18
|
|
package/dist/bin/init-local.js
CHANGED
|
@@ -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/
|
|
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".`);
|
|
@@ -105,5 +105,6 @@ export default class DefaultChangelogRenderer {
|
|
|
105
105
|
protected groupChangesByType(): Record<string, ChangelogChange[]>;
|
|
106
106
|
protected groupChangesByScope(changes: ChangelogChange[]): Record<string, ChangelogChange[]>;
|
|
107
107
|
protected extractBreakingChangeExplanation(message: string): string | null;
|
|
108
|
+
private isBreakingChangeBoundary;
|
|
108
109
|
protected formatName(name?: string): string;
|
|
109
110
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const semver_1 = require("semver");
|
|
4
|
+
// Stripped from breaking change explanations (e.g. bot/session markers).
|
|
5
|
+
const HtmlCommentRegex = /<!--[\s\S]*?-->/g;
|
|
4
6
|
class DefaultChangelogRenderer {
|
|
5
7
|
/**
|
|
6
8
|
* A ChangelogRenderer class takes in the determined changes and other relevant metadata
|
|
@@ -342,20 +344,33 @@ class DefaultChangelogRenderer {
|
|
|
342
344
|
return null;
|
|
343
345
|
}
|
|
344
346
|
const startOfBreakingChange = startIndex + breakingChangeIdentifier.length;
|
|
345
|
-
//
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
347
|
+
// A squash-merged PR body can trail the note with template sections,
|
|
348
|
+
// trailers, and git metadata. Strip comments (they can appear anywhere),
|
|
349
|
+
// then keep lines until the first boundary.
|
|
350
|
+
const lines = message
|
|
351
|
+
.slice(startOfBreakingChange)
|
|
352
|
+
.replace(HtmlCommentRegex, '')
|
|
353
|
+
.split('\n');
|
|
354
|
+
// The rest of the "BREAKING CHANGE:" line is always kept; scan from the next.
|
|
355
|
+
const explanationLines = [lines[0]];
|
|
356
|
+
for (let i = 1; i < lines.length; i++) {
|
|
357
|
+
if (this.isBreakingChangeBoundary(lines[i])) {
|
|
358
|
+
break;
|
|
356
359
|
}
|
|
360
|
+
explanationLines.push(lines[i]);
|
|
357
361
|
}
|
|
358
|
-
return
|
|
362
|
+
return explanationLines.join('\n').trim();
|
|
363
|
+
}
|
|
364
|
+
isBreakingChangeBoundary(line) {
|
|
365
|
+
const trimmed = line.trim();
|
|
366
|
+
return (
|
|
367
|
+
// Markdown heading (e.g. "## Related issues")
|
|
368
|
+
/^#{1,6}\s/.test(trimmed) ||
|
|
369
|
+
// Horizontal rule / separator
|
|
370
|
+
/^-{3,}$/.test(trimmed) ||
|
|
371
|
+
/^Co-authored-by:/i.test(trimmed) ||
|
|
372
|
+
// Git metadata delimiter following the body
|
|
373
|
+
trimmed === '"');
|
|
359
374
|
}
|
|
360
375
|
formatName(name = '') {
|
|
361
376
|
return name
|
|
@@ -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)(
|
|
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') {
|
|
@@ -80,9 +80,10 @@ function buildScopeRules(mode) {
|
|
|
80
80
|
return [
|
|
81
81
|
`<scope_rules>`,
|
|
82
82
|
`- Apply only the changes the migration prompt asks for.`,
|
|
83
|
-
`- Do not refactor
|
|
83
|
+
`- Do not refactor or update dependencies beyond what the migration prompt directs, and do not reformat files you did not change.`,
|
|
84
|
+
`- After applying your changes and before writing the handoff, format the files you created or modified so they match the workspace's style. If the workspace uses Prettier, run \`nx format:write\`, which formats your uncommitted changes; if it has no formatter configured, skip this.`,
|
|
84
85
|
`- Do not modify files outside the workspace root.`,
|
|
85
|
-
`- Do not run other \`nx\` commands that mutate workspace state (\`nx migrate\`, \`nx reset\`, \`nx run-many\`, generators, etc.). Read-only inspection (\`nx show\`, \`nx graph --file\`, reading files) is fine.`,
|
|
86
|
+
`- Do not run other \`nx\` commands that mutate workspace state (\`nx migrate\`, \`nx reset\`, \`nx run-many\`, generators, etc.), except \`nx format:write\` to format the files you changed. Read-only inspection (\`nx show\`, \`nx graph --file\`, reading files) is fine.`,
|
|
86
87
|
`- If the migration instructions are unclear, internally inconsistent, or conflict with the current workspace state, ask the user for direction (see the handoff contract). Do not guess.`,
|
|
87
88
|
`</scope_rules>`,
|
|
88
89
|
].join('\n');
|
|
@@ -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)
|
|
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
|
-
|
|
197
|
-
|
|
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';
|
|
@@ -1413,10 +1436,15 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts, fetch) {
|
|
|
1413
1436
|
// the user already has. Drop those before writing; nx migrate is
|
|
1414
1437
|
// forward-only, never a downgrade.
|
|
1415
1438
|
phase = 'package_updates';
|
|
1416
|
-
|
|
1439
|
+
// Resolve catalog: specifiers first so the filter compares real versions.
|
|
1440
|
+
const writableUpdates = (0, update_filters_1.filterDowngradedUpdates)(packageUpdates, (0, catalog_1.resolveCatalogSpecifiers)(originalPackageJson), installedPackageVersions);
|
|
1417
1441
|
const wrotePackageJson = await updatePackageJson(root, writableUpdates);
|
|
1418
1442
|
const wroteNxJsonInstallation = await updateInstallationDetails(root, writableUpdates);
|
|
1419
|
-
|
|
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);
|
|
1420
1448
|
if (migrations.length > 0) {
|
|
1421
1449
|
await createMigrationsFile(root, [
|
|
1422
1450
|
...addSplitConfigurationMigrationIfAvailable(from, writableUpdates),
|
|
@@ -1428,7 +1456,6 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts, fetch) {
|
|
|
1428
1456
|
: include === 'optional'
|
|
1429
1457
|
? `- Processed optional dependency updates only (skipped required package updates).`
|
|
1430
1458
|
: null;
|
|
1431
|
-
const resolvedTargetVersion = packageUpdates[walkedTargetPackage]?.version ?? opts.targetVersion;
|
|
1432
1459
|
// The param expressions below evaluate before the report function is
|
|
1433
1460
|
// entered; `safeReport` keeps them inside the analytics boundary so a
|
|
1434
1461
|
// param-building throw can't surface here and convert an already
|
|
@@ -137,9 +137,9 @@ async function resolveWithPolicy(packageName, version, policy, applySideEffects)
|
|
|
137
137
|
if (applySideEffects && outcome.version !== outcome.unconstrained) {
|
|
138
138
|
reportChangedOutcome(packageName, spec, outcome.version, outcome.unconstrained, policy);
|
|
139
139
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
// An immature loose pick is returned as-is. nx does not write the
|
|
141
|
+
// minimumReleaseAgeExclude entry here: migrate does not replace the install,
|
|
142
|
+
// so the real `pnpm install` (>=11.1.3) auto-writes it itself.
|
|
143
143
|
return outcome.version;
|
|
144
144
|
}
|
|
145
145
|
catch (e) {
|
|
@@ -171,28 +171,6 @@ function reportChangedOutcome(packageName, spec, picked, unconstrained, policy)
|
|
|
171
171
|
title: `Resolved ${packageName}@${picked} instead of ${unconstrained}: ${policy.sourceDescription}.`,
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
|
-
// pnpm v11 loose installs an immature version; >=11.1.3 also records it as an
|
|
175
|
-
// exclude in pnpm-workspace.yaml. Mirror that so a later real install agrees.
|
|
176
|
-
function handleImmaturePick(packageName, version, policy) {
|
|
177
|
-
if (policy.behavior.packageManager !== 'pnpm' ||
|
|
178
|
-
!policy.behavior.writesExcludes) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const added = (0, pnpm_exclude_writer_1.appendMinimumReleaseAgeExcludes)(workspace_root_1.workspaceRoot, [
|
|
182
|
-
`${packageName}@${version}`,
|
|
183
|
-
]);
|
|
184
|
-
// Already present (e.g. a prior pick or a pre-existing entry): nothing written,
|
|
185
|
-
// so do not claim we added it.
|
|
186
|
-
if (added.length === 0) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
output_1.output.log({
|
|
190
|
-
title: `Added ${packageName}@${version} to minimumReleaseAgeExclude in pnpm-workspace.yaml.`,
|
|
191
|
-
bodyLines: [
|
|
192
|
-
`It is within the ${policy.sourceDescription} window; this mirrors what pnpm would write at install time.`,
|
|
193
|
-
],
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
174
|
async function handleViolation(packageName, error, policy) {
|
|
197
175
|
const isPnpmStrict = policy.behavior.packageManager === 'pnpm' &&
|
|
198
176
|
policy.behavior.strict &&
|
|
@@ -35,7 +35,8 @@ function filterDowngradedUpdates(packageUpdates, packageJson, getInstalledVersio
|
|
|
35
35
|
if (!specifier) {
|
|
36
36
|
continue;
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
// Skip specifiers that aren't semver ranges (workspace:/npm:/git/file).
|
|
39
|
+
const floor = (0, semver_1.validRange)(specifier) ? (0, semver_1.minVersion)(specifier) : null;
|
|
39
40
|
if (floor && (0, semver_1.lt)(floor.version, resolvedNorm)) {
|
|
40
41
|
result[name] = update;
|
|
41
42
|
}
|
|
@@ -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);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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');
|
|
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,17 @@ async function connectToNxCloudWithPrompt(command) {
|
|
|
229
236
|
},
|
|
230
237
|
});
|
|
231
238
|
}
|
|
232
|
-
|
|
239
|
+
function utmContentForCommand(command) {
|
|
240
|
+
switch (command) {
|
|
241
|
+
case 'migrate':
|
|
242
|
+
return 'nx-migrate';
|
|
243
|
+
case 'view-logs':
|
|
244
|
+
return 'nx-connect';
|
|
245
|
+
default:
|
|
246
|
+
return 'nx-init';
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function nxCloudPrompt(key, utmContent) {
|
|
233
250
|
const { message, choices, initial, footer, hint } = ab_testing_1.messages.getPrompt(key);
|
|
234
251
|
const promptConfig = {
|
|
235
252
|
name: 'NxCloud',
|
|
@@ -239,7 +256,7 @@ async function nxCloudPrompt(key) {
|
|
|
239
256
|
initial,
|
|
240
257
|
}; // meeroslav: types in enquirer are not up to date
|
|
241
258
|
if (footer) {
|
|
242
|
-
promptConfig.footer = () => pc.dim(footer);
|
|
259
|
+
promptConfig.footer = () => pc.dim(`${footer} ${(0, ab_testing_1.nxCloudHyperlink)(utmContent)}`);
|
|
243
260
|
}
|
|
244
261
|
if (hint) {
|
|
245
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
|
-
|
|
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) {
|