nx 19.2.0-canary.20240604-0594deb → 19.2.0-canary.20240605-5a06daa

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 (69) 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/core/graph/main.js +1 -1
  46. package/src/daemon/tmp-dir.js +1 -1
  47. package/src/devkit-exports.d.ts +1 -1
  48. package/src/migrations/update-19-2-0/move-workspace-data-directory.d.ts +4 -0
  49. package/src/migrations/update-19-2-0/move-workspace-data-directory.js +34 -0
  50. package/src/plugins/js/index.js +2 -2
  51. package/src/plugins/js/project-graph/affected/lock-file-changes.js +11 -0
  52. package/src/plugins/js/project-graph/affected/npm-packages.js +12 -0
  53. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +3 -11
  54. package/src/plugins/js/utils/config.js +4 -0
  55. package/src/plugins/js/utils/register.d.ts +4 -3
  56. package/src/plugins/js/utils/register.js +47 -4
  57. package/src/project-graph/affected/affected-project-graph.js +6 -6
  58. package/src/project-graph/nx-deps-cache.js +6 -6
  59. package/src/project-graph/plugins/loader.js +1 -1
  60. package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
  61. package/src/tasks-runner/task-env.js +12 -0
  62. package/src/utils/cache-directory.d.ts +1 -1
  63. package/src/utils/cache-directory.js +13 -6
  64. package/src/utils/get-package-name-from-import-path.d.ts +1 -0
  65. package/src/utils/get-package-name-from-import-path.js +18 -0
  66. package/src/utils/package-json.d.ts +1 -0
  67. package/src/utils/package-manager.js +42 -9
  68. package/src/utils/params.d.ts +1 -1
  69. package/src/utils/params.js +5 -1
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.yargsReleaseCommand = void 0;
4
4
  const yargs_1 = require("yargs");
5
+ const nx_json_1 = require("../../config/nx-json");
5
6
  const logger_1 = require("../../utils/logger");
6
7
  const shared_options_1 = require("../yargs-utils/shared-options");
7
- const nx_json_1 = require("../../config/nx-json");
8
8
  exports.yargsReleaseCommand = {
9
9
  command: 'release',
10
10
  describe: 'Orchestrate versioning and publishing of applications and libraries',
@@ -13,6 +13,7 @@ exports.yargsReleaseCommand = {
13
13
  .command(versionCommand)
14
14
  .command(changelogCommand)
15
15
  .command(publishCommand)
16
+ .command(planCommand)
16
17
  .demandCommand()
17
18
  // Error on typos/mistyped CLI args, there is no reason to support arbitrary unknown args for these commands
18
19
  .strictOptions()
@@ -37,10 +38,6 @@ exports.yargsReleaseCommand = {
37
38
  .option('verbose', {
38
39
  type: 'boolean',
39
40
  describe: 'Prints additional information about the commands (e.g., stack traces)',
40
- })
41
- .option('first-release', {
42
- type: 'boolean',
43
- description: 'Indicates that this is the first release for the selected release group. If the current version cannot be determined as usual, the version on disk will be used as a fallback. This is useful when using git or the registry to determine the current version of packages, since those sources are only available after the first release. Also indicates that changelog generation should not assume a previous git tag exists and that publishing should not check for the existence of the package before running.',
44
41
  })
45
42
  .check((argv) => {
46
43
  if (argv.groups && argv.projects) {
@@ -64,7 +61,7 @@ exports.yargsReleaseCommand = {
64
61
  const releaseCommand = {
65
62
  command: '$0 [specifier]',
66
63
  describe: 'Create a version and release for the workspace, generate a changelog, and optionally publish the packages',
67
- builder: (yargs) => yargs
64
+ builder: (yargs) => withFirstReleaseOptions(yargs)
68
65
  .positional('specifier', {
69
66
  type: 'string',
70
67
  describe: 'Exact version or semver keyword to apply to the selected release group.',
@@ -90,17 +87,14 @@ const releaseCommand = {
90
87
  if (args.dryRun) {
91
88
  logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
92
89
  }
93
- if (typeof result === 'number') {
94
- process.exit(result);
95
- }
96
- process.exit(0);
90
+ process.exit(result);
97
91
  },
98
92
  };
99
93
  const versionCommand = {
100
94
  command: 'version [specifier]',
101
95
  aliases: ['v'],
102
96
  describe: 'Create a version and release for one or more applications and libraries',
103
- builder: (yargs) => withGitCommitAndGitTagOptions(yargs
97
+ builder: (yargs) => withFirstReleaseOptions(withGitCommitAndGitTagOptions(yargs
104
98
  .positional('specifier', {
105
99
  type: 'string',
106
100
  describe: 'Exact version or semver keyword to apply to the selected release group.',
@@ -113,24 +107,21 @@ const versionCommand = {
113
107
  .option('stage-changes', {
114
108
  type: 'boolean',
115
109
  describe: 'Whether or not to stage the changes made by this command. Useful when combining this command with changelog generation.',
116
- })),
110
+ }))),
117
111
  handler: async (args) => {
118
112
  const release = await Promise.resolve().then(() => require('./version'));
119
113
  const result = await release.releaseVersionCLIHandler(args);
120
114
  if (args.dryRun) {
121
115
  logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
122
116
  }
123
- if (typeof result === 'number') {
124
- process.exit(result);
125
- }
126
- process.exit(0);
117
+ process.exit(result);
127
118
  },
128
119
  };
129
120
  const changelogCommand = {
130
121
  command: 'changelog [version]',
131
122
  aliases: ['c'],
132
123
  describe: 'Generate a changelog for one or more projects, and optionally push to Github',
133
- builder: (yargs) => withGitCommitAndGitTagOptions(yargs
124
+ builder: (yargs) => withFirstReleaseOptions(withGitCommitAndGitTagOptions(yargs
134
125
  // Disable default meaning of yargs version for this command
135
126
  .version(false)
136
127
  .positional('version', {
@@ -162,24 +153,21 @@ const changelogCommand = {
162
153
  throw new Error('An explicit target version must be specified when using the changelog command directly');
163
154
  }
164
155
  return true;
165
- })),
156
+ }))),
166
157
  handler: async (args) => {
167
158
  const release = await Promise.resolve().then(() => require('./changelog'));
168
159
  const result = await release.releaseChangelogCLIHandler(args);
169
160
  if (args.dryRun) {
170
161
  logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
171
162
  }
172
- if (typeof result === 'number') {
173
- process.exit(result);
174
- }
175
- process.exit(0);
163
+ process.exit(result);
176
164
  },
177
165
  };
178
166
  const publishCommand = {
179
167
  command: 'publish',
180
168
  aliases: ['p'],
181
169
  describe: 'Publish a versioned project to a registry',
182
- builder: (yargs) => (0, shared_options_1.withRunManyOptions)((0, shared_options_1.withOutputStyleOption)(yargs))
170
+ builder: (yargs) => withFirstReleaseOptions((0, shared_options_1.withRunManyOptions)((0, shared_options_1.withOutputStyleOption)(yargs))
183
171
  .option('registry', {
184
172
  type: 'string',
185
173
  description: 'The registry to publish to',
@@ -191,7 +179,7 @@ const publishCommand = {
191
179
  .option('otp', {
192
180
  type: 'number',
193
181
  description: 'A one-time password for publishing to a registry that requires 2FA',
194
- }),
182
+ })),
195
183
  handler: async (args) => {
196
184
  const status = await (await Promise.resolve().then(() => require('./publish'))).releasePublishCLIHandler(coerceParallelOption((0, shared_options_1.withOverrides)(args, 2)));
197
185
  if (args.dryRun) {
@@ -200,6 +188,40 @@ const publishCommand = {
200
188
  process.exit(status);
201
189
  },
202
190
  };
191
+ const planCommand = {
192
+ command: 'plan [bump]',
193
+ aliases: ['pl'],
194
+ // Create a plan to pick a new version and generate a changelog entry.
195
+ // Hidden for now until the feature is more stable
196
+ describe: false,
197
+ builder: (yargs) => yargs
198
+ .positional('bump', {
199
+ type: 'string',
200
+ describe: 'Semver keyword to use for the selected release group.',
201
+ choices: [
202
+ 'major',
203
+ 'premajor',
204
+ 'minor',
205
+ 'preminor',
206
+ 'patch',
207
+ 'prepatch',
208
+ 'prerelease',
209
+ ],
210
+ })
211
+ .option('message', {
212
+ type: 'string',
213
+ alias: 'm',
214
+ describe: 'Custom message to use for the changelog entry',
215
+ }),
216
+ handler: async (args) => {
217
+ const release = await Promise.resolve().then(() => require('./plan'));
218
+ const result = await release.releasePlanCLIHandler(args);
219
+ if (args.dryRun) {
220
+ logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
221
+ }
222
+ process.exit(result);
223
+ },
224
+ };
203
225
  function coerceParallelOption(args) {
204
226
  if (args['parallel'] === 'false' || args['parallel'] === false) {
205
227
  return {
@@ -254,3 +276,9 @@ function withGitCommitAndGitTagOptions(yargs) {
254
276
  type: 'boolean',
255
277
  });
256
278
  }
279
+ function withFirstReleaseOptions(yargs) {
280
+ return yargs.option('first-release', {
281
+ type: 'boolean',
282
+ description: 'Indicates that this is the first release for the selected release group. If the current version cannot be determined as usual, the version on disk will be used as a fallback. This is useful when using git or the registry to determine the current version of packages, since those sources are only available after the first release. Also indicates that changelog generation should not assume a previous git tag exists and that publishing should not check for the existence of the package before running.',
283
+ });
284
+ }
@@ -73,12 +73,14 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
73
73
  const defaultFixedReleaseTagPattern = 'v{version}';
74
74
  const defaultIndependentReleaseTagPattern = '{projectName}@{version}';
75
75
  const workspaceProjectsRelationship = userConfig.projectsRelationship || 'fixed';
76
- const defaultGeneratorOptions = userConfig.version?.conventionalCommits
77
- ? {
78
- currentVersionResolver: 'git-tag',
79
- specifierSource: 'conventional-commits',
80
- }
81
- : {};
76
+ const defaultGeneratorOptions = {};
77
+ if (userConfig.version?.conventionalCommits) {
78
+ defaultGeneratorOptions.currentVersionResolver = 'git-tag';
79
+ defaultGeneratorOptions.specifierSource = 'conventional-commits';
80
+ }
81
+ if (userConfig.versionPlans) {
82
+ defaultGeneratorOptions.specifierSource = 'version-plans';
83
+ }
82
84
  const userGroups = Object.values(userConfig.groups ?? {});
83
85
  const disableWorkspaceChangelog = userGroups.length > 1 ||
84
86
  (userGroups.length === 1 &&
@@ -134,6 +136,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
134
136
  ? defaultIndependentReleaseTagPattern
135
137
  : defaultFixedReleaseTagPattern),
136
138
  conventionalCommits: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG,
139
+ versionPlans: false,
137
140
  };
138
141
  const groupProjectsRelationship = userConfig.projectsRelationship || WORKSPACE_DEFAULTS.projectsRelationship;
139
142
  const GROUP_DEFAULTS = {
@@ -159,6 +162,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
159
162
  groupProjectsRelationship === 'independent'
160
163
  ? defaultIndependentReleaseTagPattern
161
164
  : WORKSPACE_DEFAULTS.releaseTagPattern,
165
+ versionPlans: false,
162
166
  };
163
167
  /**
164
168
  * We first process root level config and apply defaults, so that we know how to handle the group level
@@ -187,6 +191,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
187
191
  git: userConfig.git,
188
192
  },
189
193
  ], normalizeTrueToEmptyObject(userConfig.changelog));
194
+ const rootVersionPlansConfig = userConfig.versionPlans ?? WORKSPACE_DEFAULTS.versionPlans;
190
195
  const rootConventionalCommitsConfig = deepMergeDefaults([WORKSPACE_DEFAULTS.conventionalCommits], fillUnspecifiedConventionalCommitsProperties(normalizeConventionalCommitsConfig(userConfig.conventionalCommits)));
191
196
  // these options are not supported at the group level, only the root/command level
192
197
  const rootVersionWithoutGlobalOptions = { ...rootVersionConfig };
@@ -205,6 +210,16 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
205
210
  .currentVersionResolver;
206
211
  delete rootVersionWithoutGlobalOptions.generatorOptions.specifierSource;
207
212
  }
213
+ // Apply versionPlans shorthand to the final group defaults if explicitly configured in the original user config
214
+ if (userConfig.versionPlans) {
215
+ rootVersionWithoutGlobalOptions.generatorOptions = {
216
+ ...rootVersionWithoutGlobalOptions.generatorOptions,
217
+ specifierSource: 'version-plans',
218
+ };
219
+ }
220
+ if (userConfig.versionPlans === false) {
221
+ delete rootVersionWithoutGlobalOptions.generatorOptions.specifierSource;
222
+ }
208
223
  const groups = userConfig.groups && Object.keys(userConfig.groups).length
209
224
  ? ensureProjectsConfigIsArray(userConfig.groups)
210
225
  : /**
@@ -228,6 +243,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
228
243
  releaseTagPattern: userConfig.releaseTagPattern || GROUP_DEFAULTS.releaseTagPattern,
229
244
  // Directly inherit the root level config for projectChangelogs, if set
230
245
  changelog: rootChangelogConfig.projectChangelogs || false,
246
+ versionPlans: rootVersionPlansConfig || GROUP_DEFAULTS.versionPlans,
231
247
  },
232
248
  };
233
249
  /**
@@ -298,6 +314,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
298
314
  (projectsRelationship === 'independent'
299
315
  ? defaultIndependentReleaseTagPattern
300
316
  : userConfig.releaseTagPattern || defaultFixedReleaseTagPattern),
317
+ versionPlans: releaseGroup.versionPlans ?? rootVersionPlansConfig,
301
318
  };
302
319
  const finalReleaseGroup = deepMergeDefaults([groupDefaults], {
303
320
  ...releaseGroup,
@@ -317,6 +334,20 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
317
334
  delete finalReleaseGroup.version.generatorOptions.currentVersionResolver;
318
335
  delete finalReleaseGroup.version.generatorOptions.specifierSource;
319
336
  }
337
+ // Apply versionPlans shorthand to the final group if explicitly configured in the original group
338
+ if (releaseGroup.versionPlans) {
339
+ finalReleaseGroup.version = {
340
+ ...finalReleaseGroup.version,
341
+ generatorOptions: {
342
+ ...finalReleaseGroup.version?.generatorOptions,
343
+ specifierSource: 'version-plans',
344
+ },
345
+ };
346
+ }
347
+ if (releaseGroup.versionPlans === false &&
348
+ releaseGroupName !== exports.IMPLICIT_DEFAULT_RELEASE_GROUP) {
349
+ delete finalReleaseGroup.version.generatorOptions.specifierSource;
350
+ }
320
351
  releaseGroups[releaseGroupName] = finalReleaseGroup;
321
352
  }
322
353
  ensureChangelogRenderersAreResolvable(releaseGroups, rootChangelogConfig);
@@ -330,6 +361,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
330
361
  changelog: rootChangelogConfig,
331
362
  groups: releaseGroups,
332
363
  conventionalCommits: rootConventionalCommitsConfig,
364
+ versionPlans: rootVersionPlansConfig,
333
365
  },
334
366
  };
335
367
  }
@@ -1,7 +1,9 @@
1
1
  import { ProjectGraph } from '../../../config/project-graph';
2
2
  import { NxReleaseConfig } from './config';
3
- export type ReleaseGroupWithName = NxReleaseConfig['groups'][string] & {
3
+ import { GroupVersionPlan, ProjectsVersionPlan } from './version-plans';
4
+ export type ReleaseGroupWithName = Omit<NxReleaseConfig['groups'][string], 'versionPlans'> & {
4
5
  name: string;
6
+ versionPlans: (ProjectsVersionPlan | GroupVersionPlan)[] | false;
5
7
  };
6
8
  export declare function filterReleaseGroups(projectGraph: ProjectGraph, nxReleaseConfig: NxReleaseConfig, projectsFilter?: string[], groupsFilter?: string[]): {
7
9
  error: null | {
@@ -9,6 +9,7 @@ function filterReleaseGroups(projectGraph, nxReleaseConfig, projectsFilter, grou
9
9
  return {
10
10
  ...group,
11
11
  name,
12
+ versionPlans: group.versionPlans ? [] : false,
12
13
  };
13
14
  });
14
15
  const filteredProjectToReleaseGroup = new Map();
@@ -0,0 +1,24 @@
1
+ import { ReleaseType } from 'semver';
2
+ import { ReleaseGroupWithName } from './filter-release-groups';
3
+ export interface VersionPlanFile {
4
+ absolutePath: string;
5
+ relativePath: string;
6
+ fileName: string;
7
+ createdOnMs: number;
8
+ }
9
+ export interface RawVersionPlan extends VersionPlanFile {
10
+ content: Record<string, string>;
11
+ message: string;
12
+ }
13
+ export interface VersionPlan extends VersionPlanFile {
14
+ message: string;
15
+ }
16
+ export interface GroupVersionPlan extends VersionPlan {
17
+ groupVersionBump: ReleaseType;
18
+ }
19
+ export interface ProjectsVersionPlan extends VersionPlan {
20
+ projectVersionBumps: Record<string, ReleaseType>;
21
+ }
22
+ export declare function readRawVersionPlans(): Promise<RawVersionPlan[]>;
23
+ export declare function setVersionPlansOnGroups(rawVersionPlans: RawVersionPlan[], releaseGroups: ReleaseGroupWithName[], allProjectNamesInWorkspace: string[]): ReleaseGroupWithName[];
24
+ export declare function getVersionPlansAbsolutePath(): string;
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVersionPlansAbsolutePath = exports.setVersionPlansOnGroups = exports.readRawVersionPlans = void 0;
4
+ const fs_1 = require("fs");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ const semver_1 = require("semver");
8
+ const workspace_root_1 = require("../../../utils/workspace-root");
9
+ const config_1 = require("./config");
10
+ const fm = require('front-matter');
11
+ const versionPlansDirectory = (0, path_1.join)('.nx', 'version-plans');
12
+ async function readRawVersionPlans() {
13
+ const versionPlansPath = getVersionPlansAbsolutePath();
14
+ const versionPlansPathExists = await (0, fs_extra_1.pathExists)(versionPlansPath);
15
+ if (!versionPlansPathExists) {
16
+ return [];
17
+ }
18
+ const versionPlans = [];
19
+ const versionPlanFiles = (0, fs_1.readdirSync)(versionPlansPath);
20
+ for (const versionPlanFile of versionPlanFiles) {
21
+ const filePath = (0, path_1.join)(versionPlansPath, versionPlanFile);
22
+ const versionPlanContent = (0, fs_1.readFileSync)(filePath).toString();
23
+ const versionPlanStats = await (0, fs_extra_1.stat)(filePath);
24
+ const parsedContent = fm(versionPlanContent);
25
+ versionPlans.push({
26
+ absolutePath: filePath,
27
+ relativePath: (0, path_1.join)(versionPlansDirectory, versionPlanFile),
28
+ fileName: versionPlanFile,
29
+ content: parsedContent.attributes,
30
+ message: getSingleLineMessage(parsedContent.body),
31
+ createdOnMs: versionPlanStats.birthtimeMs,
32
+ });
33
+ }
34
+ return versionPlans;
35
+ }
36
+ exports.readRawVersionPlans = readRawVersionPlans;
37
+ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNamesInWorkspace) {
38
+ const groupsByName = releaseGroups.reduce((acc, group) => acc.set(group.name, group), new Map());
39
+ const isDefaultGroup = isDefault(releaseGroups);
40
+ for (const rawVersionPlan of rawVersionPlans) {
41
+ for (const [key, value] of Object.entries(rawVersionPlan.content)) {
42
+ if (groupsByName.has(key)) {
43
+ const group = groupsByName.get(key);
44
+ if (!group.versionPlans) {
45
+ if (isDefaultGroup) {
46
+ throw new Error(`Found a version bump in '${rawVersionPlan.fileName}' but version plans are not enabled.`);
47
+ }
48
+ else {
49
+ throw new Error(`Found a version bump for group '${key}' in '${rawVersionPlan.fileName}' but the group does not have version plans enabled.`);
50
+ }
51
+ }
52
+ if (group.projectsRelationship === 'independent') {
53
+ if (isDefaultGroup) {
54
+ throw new Error(`Found a version bump in '${rawVersionPlan.fileName}' but projects are configured to be independently versioned. Individual projects should be bumped instead.`);
55
+ }
56
+ else {
57
+ throw new Error(`Found a version bump for group '${key}' in '${rawVersionPlan.fileName}' but the group's projects are independently versioned. Individual projects of '${key}' should be bumped instead.`);
58
+ }
59
+ }
60
+ if (!isReleaseType(value)) {
61
+ if (isDefaultGroup) {
62
+ throw new Error(`Found a version bump in '${rawVersionPlan.fileName}' with an invalid release type. Please specify one of ${semver_1.RELEASE_TYPES.join(', ')}.`);
63
+ }
64
+ else {
65
+ throw new Error(`Found a version bump for group '${key}' in '${rawVersionPlan.fileName}' with an invalid release type. Please specify one of ${semver_1.RELEASE_TYPES.join(', ')}.`);
66
+ }
67
+ }
68
+ const existingPlan = (group.versionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
69
+ if (existingPlan) {
70
+ if (existingPlan.groupVersionBump !== value) {
71
+ if (isDefaultGroup) {
72
+ throw new Error(`Found a version bump in '${rawVersionPlan.fileName}' that conflicts with another version bump. When in fixed versioning mode, all version bumps must match.`);
73
+ }
74
+ else {
75
+ throw new Error(`Found a version bump for group '${key}' in '${rawVersionPlan.fileName}' that conflicts with another version bump for this group. When the group is in fixed versioning mode, all groups' version bumps within the same version plan must match.`);
76
+ }
77
+ }
78
+ }
79
+ else {
80
+ group.versionPlans.push({
81
+ absolutePath: rawVersionPlan.absolutePath,
82
+ relativePath: rawVersionPlan.relativePath,
83
+ fileName: rawVersionPlan.fileName,
84
+ createdOnMs: rawVersionPlan.createdOnMs,
85
+ message: rawVersionPlan.message,
86
+ groupVersionBump: value,
87
+ });
88
+ }
89
+ }
90
+ else {
91
+ const groupForProject = releaseGroups.find((group) => group.projects.includes(key));
92
+ if (!groupForProject) {
93
+ if (!allProjectNamesInWorkspace.includes(key)) {
94
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but the project does not exist in the workspace.`);
95
+ }
96
+ if (isDefaultGroup) {
97
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but the project is not configured for release. Ensure it is included by the 'release.projects' globs in nx.json.`);
98
+ }
99
+ else {
100
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but the project is not in any configured release groups.`);
101
+ }
102
+ }
103
+ if (!groupForProject.versionPlans) {
104
+ if (isDefaultGroup) {
105
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but version plans are not enabled.`);
106
+ }
107
+ else {
108
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but the project's group '${groupForProject.name}' does not have version plans enabled.`);
109
+ }
110
+ }
111
+ if (!isReleaseType(value)) {
112
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' with an invalid release type. Please specify one of ${semver_1.RELEASE_TYPES.join(', ')}.`);
113
+ }
114
+ if (groupForProject.projectsRelationship === 'independent') {
115
+ const existingPlan = (groupForProject.versionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
116
+ if (existingPlan) {
117
+ existingPlan.projectVersionBumps[key] = value;
118
+ }
119
+ else {
120
+ groupForProject.versionPlans.push({
121
+ absolutePath: rawVersionPlan.absolutePath,
122
+ relativePath: rawVersionPlan.relativePath,
123
+ fileName: rawVersionPlan.fileName,
124
+ createdOnMs: rawVersionPlan.createdOnMs,
125
+ message: rawVersionPlan.message,
126
+ projectVersionBumps: {
127
+ [key]: value,
128
+ },
129
+ });
130
+ }
131
+ }
132
+ else {
133
+ const existingPlan = (groupForProject.versionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
134
+ // This can occur if the same fixed release group has multiple entries for different projects within
135
+ // the same version plan file. This will be the case when users are using the default release group.
136
+ if (existingPlan) {
137
+ if (existingPlan.groupVersionBump !== value) {
138
+ if (isDefaultGroup) {
139
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' that conflicts with another version bump. When in fixed versioning mode, all version bumps must match.`);
140
+ }
141
+ else {
142
+ throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' that conflicts with another project's version bump in the same release group '${groupForProject.name}'. When the group is in fixed versioning mode, all projects' version bumps within the same group must match.`);
143
+ }
144
+ }
145
+ }
146
+ else {
147
+ groupForProject.versionPlans.push({
148
+ absolutePath: rawVersionPlan.absolutePath,
149
+ relativePath: rawVersionPlan.relativePath,
150
+ fileName: rawVersionPlan.fileName,
151
+ createdOnMs: rawVersionPlan.createdOnMs,
152
+ message: rawVersionPlan.message,
153
+ // This is a fixed group, so the version bump is for the group, even if a project within it was specified
154
+ groupVersionBump: value,
155
+ });
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+ // Order the plans from newest to oldest
162
+ releaseGroups.forEach((group) => {
163
+ if (group.versionPlans) {
164
+ group.versionPlans.sort((a, b) => b.createdOnMs - a.createdOnMs);
165
+ }
166
+ });
167
+ return releaseGroups;
168
+ }
169
+ exports.setVersionPlansOnGroups = setVersionPlansOnGroups;
170
+ function isDefault(releaseGroups) {
171
+ return (releaseGroups.length === 1 &&
172
+ releaseGroups.some((group) => group.name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP));
173
+ }
174
+ function getVersionPlansAbsolutePath() {
175
+ return (0, path_1.join)(workspace_root_1.workspaceRoot, versionPlansDirectory);
176
+ }
177
+ exports.getVersionPlansAbsolutePath = getVersionPlansAbsolutePath;
178
+ function isReleaseType(value) {
179
+ return semver_1.RELEASE_TYPES.includes(value);
180
+ }
181
+ // changelog messages may only be a single line long, so ignore anything else
182
+ function getSingleLineMessage(message) {
183
+ return message.trim().split('\n')[0];
184
+ }
@@ -0,0 +1,3 @@
1
+ import { PlanOptions } from './command-object';
2
+ export declare const releasePlanCLIHandler: (args: PlanOptions) => Promise<number>;
3
+ export declare function releasePlan(args: PlanOptions): Promise<string | number>;