nx 19.2.0-canary.20240604-0594deb → 19.2.0-rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/migrations.json +6 -0
  2. package/package.json +13 -12
  3. package/release/changelog-renderer/index.d.ts +6 -3
  4. package/release/changelog-renderer/index.js +53 -50
  5. package/schemas/nx-schema.json +8 -0
  6. package/src/command-line/add/add.d.ts +1 -1
  7. package/src/command-line/add/command-object.js +3 -1
  8. package/src/command-line/affected/command-object.js +10 -5
  9. package/src/command-line/deprecated/command-objects.js +12 -6
  10. package/src/command-line/examples.js +18 -0
  11. package/src/command-line/generate/generate.d.ts +1 -1
  12. package/src/command-line/migrate/migrate.d.ts +1 -1
  13. package/src/command-line/new/new.d.ts +1 -1
  14. package/src/command-line/release/changelog.d.ts +17 -1
  15. package/src/command-line/release/changelog.js +305 -76
  16. package/src/command-line/release/command-object.d.ts +14 -5
  17. package/src/command-line/release/command-object.js +52 -24
  18. package/src/command-line/release/config/config.js +38 -6
  19. package/src/command-line/release/config/filter-release-groups.d.ts +3 -1
  20. package/src/command-line/release/config/filter-release-groups.js +1 -0
  21. package/src/command-line/release/config/version-plans.d.ts +24 -0
  22. package/src/command-line/release/config/version-plans.js +184 -0
  23. package/src/command-line/release/plan.d.ts +3 -0
  24. package/src/command-line/release/plan.js +184 -0
  25. package/src/command-line/release/publish.d.ts +1 -1
  26. package/src/command-line/release/release.d.ts +1 -1
  27. package/src/command-line/release/release.js +40 -0
  28. package/src/command-line/release/utils/git.d.ts +10 -2
  29. package/src/command-line/release/utils/git.js +45 -10
  30. package/src/command-line/release/utils/shared.d.ts +12 -2
  31. package/src/command-line/release/utils/shared.js +3 -2
  32. package/src/command-line/release/version.d.ts +3 -2
  33. package/src/command-line/release/version.js +43 -5
  34. package/src/command-line/repair/repair.d.ts +1 -1
  35. package/src/command-line/reset/command-object.d.ts +6 -1
  36. package/src/command-line/reset/command-object.js +15 -2
  37. package/src/command-line/reset/reset.d.ts +2 -1
  38. package/src/command-line/reset/reset.js +98 -16
  39. package/src/command-line/run/command-object.js +6 -3
  40. package/src/command-line/run/run.d.ts +2 -2
  41. package/src/command-line/run-many/command-object.js +6 -3
  42. package/src/command-line/show/command-object.js +6 -6
  43. package/src/config/misc-interfaces.d.ts +15 -3
  44. package/src/config/nx-json.d.ts +11 -0
  45. package/src/daemon/tmp-dir.js +1 -1
  46. package/src/devkit-exports.d.ts +1 -1
  47. package/src/migrations/update-19-2-0/move-workspace-data-directory.d.ts +4 -0
  48. package/src/migrations/update-19-2-0/move-workspace-data-directory.js +34 -0
  49. package/src/plugins/js/index.js +2 -2
  50. package/src/plugins/js/project-graph/affected/lock-file-changes.js +11 -0
  51. package/src/plugins/js/project-graph/affected/npm-packages.js +12 -0
  52. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +3 -11
  53. package/src/plugins/js/utils/config.js +4 -0
  54. package/src/plugins/js/utils/register.d.ts +4 -3
  55. package/src/plugins/js/utils/register.js +47 -4
  56. package/src/project-graph/affected/affected-project-graph.js +6 -6
  57. package/src/project-graph/nx-deps-cache.js +6 -6
  58. package/src/project-graph/plugins/loader.js +1 -1
  59. package/src/tasks-runner/task-env.js +12 -0
  60. package/src/utils/cache-directory.d.ts +1 -1
  61. package/src/utils/cache-directory.js +13 -6
  62. package/src/utils/get-package-name-from-import-path.d.ts +1 -0
  63. package/src/utils/get-package-name-from-import-path.js +18 -0
  64. package/src/utils/package-json.d.ts +1 -0
  65. package/src/utils/package-manager.js +42 -9
  66. package/src/utils/params.d.ts +1 -1
  67. package/src/utils/params.js +5 -1
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.releasePlan = exports.releasePlanCLIHandler = void 0;
4
+ const enquirer_1 = require("enquirer");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ const semver_1 = require("semver");
8
+ const nx_json_1 = require("../../config/nx-json");
9
+ const file_map_utils_1 = require("../../project-graph/file-map-utils");
10
+ const project_graph_1 = require("../../project-graph/project-graph");
11
+ const output_1 = require("../../utils/output");
12
+ const params_1 = require("../../utils/params");
13
+ const config_1 = require("./config/config");
14
+ const filter_release_groups_1 = require("./config/filter-release-groups");
15
+ const version_plans_1 = require("./config/version-plans");
16
+ const git_1 = require("./utils/git");
17
+ const print_changes_1 = require("./utils/print-changes");
18
+ const releasePlanCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => releasePlan(args));
19
+ exports.releasePlanCLIHandler = releasePlanCLIHandler;
20
+ async function releasePlan(args) {
21
+ const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
22
+ const nxJson = (0, nx_json_1.readNxJson)();
23
+ if (args.verbose) {
24
+ process.env.NX_VERBOSE_LOGGING = 'true';
25
+ }
26
+ // Apply default configuration to any optional user configuration
27
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
28
+ if (configError) {
29
+ return await (0, config_1.handleNxReleaseConfigError)(configError);
30
+ }
31
+ const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
32
+ if (filterError) {
33
+ output_1.output.error(filterError);
34
+ process.exit(1);
35
+ }
36
+ const versionPlanBumps = {};
37
+ const setBumpIfNotNone = (projectOrGroup, version) => {
38
+ if (version !== 'none') {
39
+ versionPlanBumps[projectOrGroup] = version;
40
+ }
41
+ };
42
+ if (args.message) {
43
+ const message = (0, git_1.parseConventionalCommitsMessage)(args.message);
44
+ if (!message) {
45
+ output_1.output.error({
46
+ title: 'Changelog message is not in conventional commits format.',
47
+ bodyLines: [
48
+ 'Please ensure your message is in the form of:',
49
+ ' type(optional scope): description',
50
+ '',
51
+ 'For example:',
52
+ ' feat(pkg-b): add new feature',
53
+ ' fix(pkg-a): correct a bug',
54
+ ' chore: update build process',
55
+ ' fix(core)!: breaking change in core package',
56
+ ],
57
+ });
58
+ process.exit(1);
59
+ }
60
+ }
61
+ if (releaseGroups[0].name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
62
+ const group = releaseGroups[0];
63
+ if (group.projectsRelationship === 'independent') {
64
+ for (const project of group.projects) {
65
+ setBumpIfNotNone(project, args.bump ||
66
+ (await promptForVersion(`How do you want to bump the version of the project "${project}"?`)));
67
+ }
68
+ }
69
+ else {
70
+ // TODO: use project names instead of the implicit default release group name? (though this might be confusing, as users might think they can just delete one of the project bumps to change the behavior to independent versioning)
71
+ setBumpIfNotNone(group.name, args.bump ||
72
+ (await promptForVersion(`How do you want to bump the versions of all projects?`)));
73
+ }
74
+ }
75
+ else {
76
+ for (const group of releaseGroups) {
77
+ if (group.projectsRelationship === 'independent') {
78
+ for (const project of releaseGroupToFilteredProjects.get(group)) {
79
+ setBumpIfNotNone(project, args.bump ||
80
+ (await promptForVersion(`How do you want to bump the version of the project "${project}" within group "${group.name}"?`)));
81
+ }
82
+ }
83
+ else {
84
+ setBumpIfNotNone(group.name, args.bump ||
85
+ (await promptForVersion(`How do you want to bump the versions of the projects in the group "${group.name}"?`)));
86
+ }
87
+ }
88
+ }
89
+ if (!Object.keys(versionPlanBumps).length) {
90
+ output_1.output.warn({
91
+ title: 'No version bumps were selected so no version plan file was created.',
92
+ });
93
+ return 0;
94
+ }
95
+ const versionPlanMessage = args.message || (await promptForMessage());
96
+ const versionPlanFileContent = getVersionPlanFileContent(versionPlanBumps, versionPlanMessage);
97
+ const versionPlanFileName = `version-plan-${new Date().getTime()}.md`;
98
+ if (args.dryRun) {
99
+ output_1.output.logSingleLine(`Would create version plan file "${versionPlanFileName}", but --dry-run was set.`);
100
+ (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
101
+ }
102
+ else {
103
+ output_1.output.logSingleLine(`Creating version plan file "${versionPlanFileName}"`);
104
+ (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
105
+ const versionPlansAbsolutePath = (0, version_plans_1.getVersionPlansAbsolutePath)();
106
+ await (0, fs_extra_1.ensureDir)(versionPlansAbsolutePath);
107
+ await (0, fs_extra_1.writeFile)((0, path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
108
+ }
109
+ return 0;
110
+ }
111
+ exports.releasePlan = releasePlan;
112
+ async function promptForVersion(message) {
113
+ try {
114
+ const reply = await (0, enquirer_1.prompt)([
115
+ {
116
+ name: 'version',
117
+ message,
118
+ type: 'select',
119
+ choices: [...semver_1.RELEASE_TYPES, 'none'],
120
+ },
121
+ ]);
122
+ return reply.version;
123
+ }
124
+ catch (e) {
125
+ output_1.output.log({
126
+ title: 'Cancelled version plan creation.',
127
+ });
128
+ process.exit(0);
129
+ }
130
+ }
131
+ async function promptForMessage() {
132
+ let message;
133
+ do {
134
+ message = await _promptForMessage();
135
+ } while (!message);
136
+ return message;
137
+ }
138
+ // TODO: support non-conventional commits messages (will require significant changelog renderer changes)
139
+ async function _promptForMessage() {
140
+ try {
141
+ const reply = await (0, enquirer_1.prompt)([
142
+ {
143
+ name: 'message',
144
+ message: 'What changelog message would you like associated with this change?',
145
+ type: 'input',
146
+ },
147
+ ]);
148
+ const conventionalCommitsMessage = (0, git_1.parseConventionalCommitsMessage)(reply.message);
149
+ if (!conventionalCommitsMessage) {
150
+ output_1.output.warn({
151
+ title: 'Changelog message is not in conventional commits format.',
152
+ bodyLines: [
153
+ 'Please ensure your message is in the form of:',
154
+ ' type(optional scope): description',
155
+ '',
156
+ 'For example:',
157
+ ' feat(pkg-b): add new feature',
158
+ ' fix(pkg-a): correct a bug',
159
+ ' chore: update build process',
160
+ ' fix(core)!: breaking change in core package',
161
+ ],
162
+ });
163
+ return null;
164
+ }
165
+ return reply.message;
166
+ }
167
+ catch (e) {
168
+ output_1.output.log({
169
+ title: 'Cancelled version plan creation.',
170
+ });
171
+ process.exit(0);
172
+ }
173
+ }
174
+ function getVersionPlanFileContent(bumps, message) {
175
+ return `---
176
+ ${Object.entries(bumps)
177
+ .filter(([_, version]) => version !== 'none')
178
+ .map(([projectOrGroup, version]) => `${projectOrGroup}: ${version}`)
179
+ .join('\n')}
180
+ ---
181
+
182
+ ${message}
183
+ `;
184
+ }
@@ -1,5 +1,5 @@
1
1
  import { PublishOptions } from './command-object';
2
- export declare const releasePublishCLIHandler: (args: PublishOptions) => Promise<any>;
2
+ export declare const releasePublishCLIHandler: (args: PublishOptions) => Promise<number>;
3
3
  /**
4
4
  * NOTE: This function is also exported for programmatic usage and forms part of the public API
5
5
  * of Nx. We intentionally do not wrap the implementation with handleErrors because users need
@@ -1,4 +1,4 @@
1
1
  import { ReleaseOptions, VersionOptions } from './command-object';
2
2
  import { NxReleaseVersionResult } from './version';
3
- export declare const releaseCLIHandler: (args: VersionOptions) => Promise<any>;
3
+ export declare const releaseCLIHandler: (args: VersionOptions) => Promise<number>;
4
4
  export declare function release(args: ReleaseOptions): Promise<NxReleaseVersionResult | number>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.release = exports.releaseCLIHandler = void 0;
4
4
  const enquirer_1 = require("enquirer");
5
+ const fs_extra_1 = require("fs-extra");
5
6
  const nx_json_1 = require("../../config/nx-json");
6
7
  const file_map_utils_1 = require("../../project-graph/file-map-utils");
7
8
  const project_graph_1 = require("../../project-graph/project-graph");
@@ -10,6 +11,7 @@ const params_1 = require("../../utils/params");
10
11
  const changelog_1 = require("./changelog");
11
12
  const config_1 = require("./config/config");
12
13
  const filter_release_groups_1 = require("./config/filter-release-groups");
14
+ const version_plans_1 = require("./config/version-plans");
13
15
  const publish_1 = require("./publish");
14
16
  const git_1 = require("./utils/git");
15
17
  const github_1 = require("./utils/github");
@@ -52,6 +54,7 @@ async function release(args) {
52
54
  stageChanges: shouldStage,
53
55
  gitCommit: false,
54
56
  gitTag: false,
57
+ deleteVersionPlans: false,
55
58
  });
56
59
  const changelogResult = await (0, changelog_1.releaseChangelog)({
57
60
  ...args,
@@ -61,12 +64,49 @@ async function release(args) {
61
64
  gitCommit: false,
62
65
  gitTag: false,
63
66
  createRelease: false,
67
+ deleteVersionPlans: false,
64
68
  });
65
69
  const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
66
70
  if (filterError) {
67
71
  output_1.output.error(filterError);
68
72
  process.exit(1);
69
73
  }
74
+ const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
75
+ (0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
76
+ const planFiles = new Set();
77
+ releaseGroups.forEach((group) => {
78
+ if (group.versionPlans) {
79
+ if (group.name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
80
+ output_1.output.logSingleLine(`Removing version plan files`);
81
+ }
82
+ else {
83
+ output_1.output.logSingleLine(`Removing version plan files for group ${group.name}`);
84
+ }
85
+ group.versionPlans.forEach((plan) => {
86
+ if (!args.dryRun) {
87
+ (0, fs_extra_1.removeSync)(plan.absolutePath);
88
+ if (args.verbose) {
89
+ console.log(`Removing ${plan.relativePath}`);
90
+ }
91
+ }
92
+ else {
93
+ if (args.verbose) {
94
+ console.log(`Would remove ${plan.relativePath}, but --dry-run was set`);
95
+ }
96
+ }
97
+ planFiles.add(plan.relativePath);
98
+ });
99
+ }
100
+ });
101
+ const deletedFiles = Array.from(planFiles);
102
+ if (deletedFiles.length > 0) {
103
+ await (0, git_1.gitAdd)({
104
+ changedFiles: [],
105
+ deletedFiles,
106
+ dryRun: args.dryRun,
107
+ verbose: args.verbose,
108
+ });
109
+ }
70
110
  if (shouldCommit) {
71
111
  output_1.output.logSingleLine(`Committing changes with git`);
72
112
  const commitMessage = nxReleaseConfig.git.commitMessage;
@@ -27,8 +27,10 @@ export declare function getLatestGitTagForPattern(releaseTagPattern: string, add
27
27
  extractedVersion: string;
28
28
  } | null>;
29
29
  export declare function getGitDiff(from: string | undefined, to?: string): Promise<RawGitCommit[]>;
30
- export declare function gitAdd({ changedFiles, dryRun, verbose, logFn, }: {
31
- changedFiles: string[];
30
+ export declare function getChangedTrackedFiles(): Promise<Set<string>>;
31
+ export declare function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, }: {
32
+ changedFiles?: string[];
33
+ deletedFiles?: string[];
32
34
  dryRun?: boolean;
33
35
  verbose?: boolean;
34
36
  logFn?: (...messages: string[]) => void;
@@ -54,6 +56,12 @@ export declare function gitPush({ gitRemote, dryRun, verbose, }: {
54
56
  verbose?: boolean;
55
57
  }): Promise<void>;
56
58
  export declare function parseCommits(commits: RawGitCommit[]): GitCommit[];
59
+ export declare function parseConventionalCommitsMessage(message: string): {
60
+ type: string;
61
+ scope: string;
62
+ description: string;
63
+ breaking: boolean;
64
+ } | null;
57
65
  export declare function parseGitCommit(commit: RawGitCommit): GitCommit | null;
58
66
  export declare function getCommitHash(ref: string): Promise<string>;
59
67
  export declare function getFirstGitCommit(): Promise<string>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFirstGitCommit = exports.getCommitHash = exports.parseGitCommit = exports.parseCommits = exports.gitPush = exports.gitTag = exports.gitCommit = exports.gitAdd = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
3
+ exports.getFirstGitCommit = exports.getCommitHash = exports.parseGitCommit = exports.parseConventionalCommitsMessage = exports.parseCommits = exports.gitPush = exports.gitTag = exports.gitCommit = exports.gitAdd = exports.getChangedTrackedFiles = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
4
4
  /**
5
5
  * Special thanks to changelogen for the original inspiration for many of these utilities:
6
6
  * https://github.com/unjs/changelogen
@@ -97,11 +97,17 @@ async function getGitDiff(from, to = 'HEAD') {
97
97
  });
98
98
  }
99
99
  exports.getGitDiff = getGitDiff;
100
- async function gitAdd({ changedFiles, dryRun, verbose, logFn, }) {
100
+ async function getChangedTrackedFiles() {
101
+ const result = await (0, exec_command_1.execCommand)('git', ['status', '--porcelain']);
102
+ const lines = result.split('\n').filter((l) => l.trim().length > 0);
103
+ return new Set(lines.map((l) => l.substring(3)));
104
+ }
105
+ exports.getChangedTrackedFiles = getChangedTrackedFiles;
106
+ async function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, }) {
101
107
  logFn = logFn || console.log;
102
108
  let ignoredFiles = [];
103
109
  let filesToAdd = [];
104
- for (const f of changedFiles) {
110
+ for (const f of changedFiles ?? []) {
105
111
  const isFileIgnored = await isIgnored(f);
106
112
  if (isFileIgnored) {
107
113
  ignoredFiles.push(f);
@@ -110,12 +116,28 @@ async function gitAdd({ changedFiles, dryRun, verbose, logFn, }) {
110
116
  filesToAdd.push(f);
111
117
  }
112
118
  }
119
+ if (deletedFiles?.length > 0) {
120
+ const changedTrackedFiles = await getChangedTrackedFiles();
121
+ for (const f of deletedFiles ?? []) {
122
+ const isFileIgnored = await isIgnored(f);
123
+ if (isFileIgnored) {
124
+ ignoredFiles.push(f);
125
+ // git add will fail if trying to add an untracked file that doesn't exist
126
+ }
127
+ else if (changedTrackedFiles.has(f)) {
128
+ filesToAdd.push(f);
129
+ }
130
+ }
131
+ }
113
132
  if (verbose && ignoredFiles.length) {
114
133
  logFn(`Will not add the following files because they are ignored by git:`);
115
134
  ignoredFiles.forEach((f) => logFn(f));
116
135
  }
117
136
  if (!filesToAdd.length) {
118
- logFn('\nNo files to stage. Skipping git add.');
137
+ if (!dryRun) {
138
+ logFn('\nNo files to stage. Skipping git add.');
139
+ }
140
+ // if this is a dry run, it's possible that there would have been actual files to add, so it's deceptive to say "No files to stage".
119
141
  return;
120
142
  }
121
143
  const commandArgs = ['add', ...filesToAdd];
@@ -236,6 +258,19 @@ function parseCommits(commits) {
236
258
  return commits.map((commit) => parseGitCommit(commit)).filter(Boolean);
237
259
  }
238
260
  exports.parseCommits = parseCommits;
261
+ function parseConventionalCommitsMessage(message) {
262
+ const match = message.match(ConventionalCommitRegex);
263
+ if (!match) {
264
+ return null;
265
+ }
266
+ return {
267
+ type: match.groups.type || '',
268
+ scope: match.groups.scope || '',
269
+ description: match.groups.description || '',
270
+ breaking: Boolean(match.groups.breaking),
271
+ };
272
+ }
273
+ exports.parseConventionalCommitsMessage = parseConventionalCommitsMessage;
239
274
  // https://www.conventionalcommits.org/en/v1.0.0/
240
275
  // https://regex101.com/r/FSfNvA/1
241
276
  const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
@@ -245,13 +280,13 @@ const IssueRE = /(#\d+)/gm;
245
280
  const ChangedFileRegex = /(A|M|D|R\d*|C\d*)\t([^\t\n]*)\t?(.*)?/gm;
246
281
  const RevertHashRE = /This reverts commit (?<hash>[\da-f]{40})./gm;
247
282
  function parseGitCommit(commit) {
248
- const match = commit.message.match(ConventionalCommitRegex);
249
- if (!match) {
283
+ const parsedMessage = parseConventionalCommitsMessage(commit.message);
284
+ if (!parsedMessage) {
250
285
  return null;
251
286
  }
252
- const scope = match.groups.scope || '';
253
- const isBreaking = Boolean(match.groups.breaking) || commit.body.includes('BREAKING CHANGE:');
254
- let description = match.groups.description;
287
+ const scope = parsedMessage.scope;
288
+ const isBreaking = parsedMessage.breaking || commit.body.includes('BREAKING CHANGE:');
289
+ let description = parsedMessage.description;
255
290
  // Extract references from message
256
291
  const references = [];
257
292
  for (const m of description.matchAll(PullRequestRE)) {
@@ -265,7 +300,7 @@ function parseGitCommit(commit) {
265
300
  references.push({ value: commit.shortHash, type: 'hash' });
266
301
  // Remove references and normalize
267
302
  description = description.replace(PullRequestRE, '').trim();
268
- let type = match.groups.type;
303
+ let type = parsedMessage.type;
269
304
  // Extract any reverted hashes, if applicable
270
305
  const revertedHashes = [];
271
306
  const matchedHashes = commit.body.matchAll(RevertHashRE);
@@ -9,7 +9,10 @@ export type ReleaseVersionGeneratorResult = {
9
9
  dryRun?: boolean;
10
10
  verbose?: boolean;
11
11
  generatorOptions?: Record<string, unknown>;
12
- }) => Promise<string[]>;
12
+ }) => Promise<string[] | {
13
+ changedFiles: string[];
14
+ deletedFiles: string[];
15
+ }>;
13
16
  };
14
17
  export type VersionData = Record<string, {
15
18
  /**
@@ -36,7 +39,14 @@ export declare class ReleaseVersion {
36
39
  projectName?: string;
37
40
  });
38
41
  }
39
- export declare function commitChanges(changedFiles: string[], isDryRun: boolean, isVerbose: boolean, gitCommitMessages: string[], gitCommitArgs?: string): Promise<void>;
42
+ export declare function commitChanges({ changedFiles, deletedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs, }: {
43
+ changedFiles?: string[];
44
+ deletedFiles?: string[];
45
+ isDryRun?: boolean;
46
+ isVerbose?: boolean;
47
+ gitCommitMessages?: string[];
48
+ gitCommitArgs?: string;
49
+ }): Promise<void>;
40
50
  export declare function createCommitMessageValues(releaseGroups: ReleaseGroupWithName[], releaseGroupToFilteredProjects: Map<ReleaseGroupWithName, Set<string>>, versionData: VersionData, commitMessage: string): string[];
41
51
  export declare function createGitTagValues(releaseGroups: ReleaseGroupWithName[], releaseGroupToFilteredProjects: Map<ReleaseGroupWithName, Set<string>>, versionData: VersionData): string[];
42
52
  export declare function handleDuplicateGitTags(gitTagValues: string[]): void;
@@ -26,13 +26,14 @@ class ReleaseVersion {
26
26
  }
27
27
  }
28
28
  exports.ReleaseVersion = ReleaseVersion;
29
- async function commitChanges(changedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs) {
30
- if (!changedFiles.length) {
29
+ async function commitChanges({ changedFiles, deletedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs, }) {
30
+ if (!changedFiles?.length && !deletedFiles?.length) {
31
31
  throw new Error('Error: No changed files to commit');
32
32
  }
33
33
  output_1.output.logSingleLine(`Committing changes with git`);
34
34
  await (0, git_1.gitAdd)({
35
35
  changedFiles,
36
+ deletedFiles,
36
37
  dryRun: isDryRun,
37
38
  verbose: isVerbose,
38
39
  });
@@ -11,7 +11,7 @@ export interface ReleaseVersionGeneratorSchema {
11
11
  releaseGroup: ReleaseGroupWithName;
12
12
  projectGraph: ProjectGraph;
13
13
  specifier?: string;
14
- specifierSource?: 'prompt' | 'conventional-commits';
14
+ specifierSource?: 'prompt' | 'conventional-commits' | 'version-plans';
15
15
  preid?: string;
16
16
  packageRoot?: string;
17
17
  currentVersionResolver?: 'registry' | 'disk' | 'git-tag';
@@ -23,6 +23,7 @@ export interface ReleaseVersionGeneratorSchema {
23
23
  installArgs?: string;
24
24
  installIgnoreScripts?: boolean;
25
25
  conventionalCommitsConfig?: NxReleaseConfig['conventionalCommits'];
26
+ deleteVersionPlans?: boolean;
26
27
  /**
27
28
  * 'auto' allows users to opt into dependents being updated (a patch version bump) when a dependency is versioned.
28
29
  * This is only applicable to independently released projects.
@@ -43,7 +44,7 @@ export interface NxReleaseVersionResult {
43
44
  workspaceVersion: (string | null) | undefined;
44
45
  projectsVersionData: VersionData;
45
46
  }
46
- export declare const releaseVersionCLIHandler: (args: VersionOptions) => Promise<any>;
47
+ export declare const releaseVersionCLIHandler: (args: VersionOptions) => Promise<number>;
47
48
  /**
48
49
  * NOTE: This function is also exported for programmatic usage and forms part of the public API
49
50
  * of Nx. We intentionally do not wrap the implementation with handleErrors because users need
@@ -17,6 +17,7 @@ const generate_1 = require("../generate/generate");
17
17
  const generator_utils_1 = require("../generate/generator-utils");
18
18
  const config_1 = require("./config/config");
19
19
  const filter_release_groups_1 = require("./config/filter-release-groups");
20
+ const version_plans_1 = require("./config/version-plans");
20
21
  const batch_projects_by_generator_config_1 = require("./utils/batch-projects-by-generator-config");
21
22
  const git_1 = require("./utils/git");
22
23
  const print_changes_1 = require("./utils/print-changes");
@@ -69,6 +70,12 @@ async function releaseVersion(args) {
69
70
  output_1.output.error(filterError);
70
71
  process.exit(1);
71
72
  }
73
+ const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
74
+ (0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
75
+ if (args.deleteVersionPlans === undefined) {
76
+ // default to not delete version plans after versioning as they may be needed for changelog generation
77
+ args.deleteVersionPlans = false;
78
+ }
72
79
  runPreVersionCommand(nxReleaseConfig.version.preVersionCommand, {
73
80
  dryRun: args.dryRun,
74
81
  verbose: args.verbose,
@@ -82,6 +89,7 @@ async function releaseVersion(args) {
82
89
  * and need to get staged and committed as part of the existing commit, if applicable.
83
90
  */
84
91
  const additionalChangedFiles = new Set();
92
+ const additionalDeletedFiles = new Set();
85
93
  if (args.projects?.length) {
86
94
  /**
87
95
  * Run versioning for all remaining release groups and filtered projects within them
@@ -104,7 +112,7 @@ async function releaseVersion(args) {
104
112
  const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
105
113
  // Capture the callback so that we can run it after flushing the changes to disk
106
114
  generatorCallbacks.push(async () => {
107
- const changedFiles = await generatorCallback(tree, {
115
+ const result = await generatorCallback(tree, {
108
116
  dryRun: !!args.dryRun,
109
117
  verbose: !!args.verbose,
110
118
  generatorOptions: {
@@ -112,7 +120,9 @@ async function releaseVersion(args) {
112
120
  ...args.generatorOptionsOverrides,
113
121
  },
114
122
  });
123
+ const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
115
124
  changedFiles.forEach((f) => additionalChangedFiles.add(f));
125
+ deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
116
126
  });
117
127
  }
118
128
  }
@@ -138,7 +148,14 @@ async function releaseVersion(args) {
138
148
  };
139
149
  }
140
150
  if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
141
- await (0, shared_1.commitChanges)(changedFiles, !!args.dryRun, !!args.verbose, (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage), args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs);
151
+ await (0, shared_1.commitChanges)({
152
+ changedFiles,
153
+ deletedFiles: Array.from(additionalDeletedFiles),
154
+ isDryRun: !!args.dryRun,
155
+ isVerbose: !!args.verbose,
156
+ gitCommitMessages: (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage),
157
+ gitCommitArgs: args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs,
158
+ });
142
159
  }
143
160
  else if (args.stageChanges ?? nxReleaseConfig.version.git.stageChanges) {
144
161
  output_1.output.logSingleLine(`Staging changed files with git`);
@@ -186,7 +203,7 @@ async function releaseVersion(args) {
186
203
  const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
187
204
  // Capture the callback so that we can run it after flushing the changes to disk
188
205
  generatorCallbacks.push(async () => {
189
- const changedFiles = await generatorCallback(tree, {
206
+ const result = await generatorCallback(tree, {
190
207
  dryRun: !!args.dryRun,
191
208
  verbose: !!args.verbose,
192
209
  generatorOptions: {
@@ -194,7 +211,9 @@ async function releaseVersion(args) {
194
211
  ...args.generatorOptionsOverrides,
195
212
  },
196
213
  });
214
+ const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
197
215
  changedFiles.forEach((f) => additionalChangedFiles.add(f));
216
+ deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
198
217
  });
199
218
  }
200
219
  }
@@ -228,7 +247,14 @@ async function releaseVersion(args) {
228
247
  };
229
248
  }
230
249
  if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
231
- await (0, shared_1.commitChanges)(changedFiles, !!args.dryRun, !!args.verbose, (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage), args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs);
250
+ await (0, shared_1.commitChanges)({
251
+ changedFiles,
252
+ deletedFiles: Array.from(additionalDeletedFiles),
253
+ isDryRun: !!args.dryRun,
254
+ isVerbose: !!args.verbose,
255
+ gitCommitMessages: (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage),
256
+ gitCommitArgs: args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs,
257
+ });
232
258
  }
233
259
  else if (args.stageChanges ?? nxReleaseConfig.version.git.stageChanges) {
234
260
  output_1.output.logSingleLine(`Staging changed files with git`);
@@ -279,6 +305,7 @@ async function runVersionOnProjects(projectGraph, nxJson, args, tree, generatorD
279
305
  releaseGroup,
280
306
  firstRelease: args.firstRelease ?? false,
281
307
  conventionalCommitsConfig,
308
+ deleteVersionPlans: args.deleteVersionPlans,
282
309
  };
283
310
  // Apply generator defaults from schema.json file etc
284
311
  const combinedOpts = await (0, params_1.combineOptionsForGenerator)(generatorOptions, generatorData.collectionName, generatorData.normalizedGeneratorName, (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), nxJson, generatorData.schema, false, null, (0, node_path_1.relative)(process.cwd(), workspace_root_1.workspaceRoot), args.verbose);
@@ -306,7 +333,7 @@ function printAndFlushChanges(tree, isDryRun) {
306
333
  const currentContentsOnDisk = (0, node_fs_1.readFileSync)((0, path_1.joinPathFragments)(tree.root, f.path)).toString();
307
334
  (0, print_changes_1.printDiff)(currentContentsOnDisk, f.content?.toString() || '');
308
335
  }
309
- else if (f.type === 'DELETE') {
336
+ else if (f.type === 'DELETE' && !f.path.includes('.nx')) {
310
337
  throw new Error('Unexpected DELETE change, please report this as an issue');
311
338
  }
312
339
  });
@@ -395,3 +422,14 @@ function runPreVersionCommand(preVersionCommand, { dryRun, verbose }) {
395
422
  process.exit(1);
396
423
  }
397
424
  }
425
+ function parseGeneratorCallbackResult(result) {
426
+ if (Array.isArray(result)) {
427
+ return {
428
+ changedFiles: result,
429
+ deletedFiles: [],
430
+ };
431
+ }
432
+ else {
433
+ return result;
434
+ }
435
+ }
@@ -1,3 +1,3 @@
1
1
  export declare function repair(args: {
2
2
  verbose: boolean;
3
- }, extraMigrations?: any[]): Promise<any>;
3
+ }, extraMigrations?: any[]): Promise<number>;
@@ -1,2 +1,7 @@
1
1
  import { CommandModule } from 'yargs';
2
- export declare const yargsResetCommand: CommandModule;
2
+ export type ResetCommandOptions = {
3
+ onlyCache?: boolean;
4
+ onlyDaemon?: boolean;
5
+ onlyWorkspaceData?: boolean;
6
+ };
7
+ export declare const yargsResetCommand: CommandModule<Record<string, unknown>, ResetCommandOptions>;
@@ -3,7 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.yargsResetCommand = void 0;
4
4
  exports.yargsResetCommand = {
5
5
  command: 'reset',
6
- describe: 'Clears all the cached Nx artifacts and metadata about the workspace and shuts down the Nx Daemon.',
6
+ describe: 'Clears cached Nx artifacts and metadata about the workspace and shuts down the Nx Daemon.',
7
7
  aliases: ['clear-cache'],
8
- handler: async () => (await Promise.resolve().then(() => require('./reset'))).resetHandler(),
8
+ builder: (yargs) => yargs
9
+ .option('onlyCache', {
10
+ description: 'Clears the Nx cache directory. This will remove all local cache entries for tasks, but will not affect the remote cache.',
11
+ type: 'boolean',
12
+ })
13
+ .option('onlyDaemon', {
14
+ description: 'Stops the Nx Daemon, it will be restarted fresh when the next Nx command is run.',
15
+ type: 'boolean',
16
+ })
17
+ .option('onlyWorkspaceData', {
18
+ description: 'Clears the workspace data directory. Used by Nx to store cached data about the current workspace (e.g. partial results, incremental data, etc)',
19
+ type: 'boolean',
20
+ }),
21
+ handler: async (argv) => (await Promise.resolve().then(() => require('./reset'))).resetHandler(argv),
9
22
  };
@@ -1 +1,2 @@
1
- export declare function resetHandler(): Promise<void>;
1
+ import { ResetCommandOptions } from './command-object';
2
+ export declare function resetHandler(args: ResetCommandOptions): Promise<void>;