nx 19.6.0-beta.0 → 19.6.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. package/bin/post-install.js +8 -0
  2. package/package.json +12 -12
  3. package/release/changelog-renderer/index.js +16 -1
  4. package/schemas/nx-schema.json +25 -0
  5. package/schemas/project-schema.json +7 -0
  6. package/src/adapter/compat.d.ts +1 -1
  7. package/src/adapter/compat.js +1 -0
  8. package/src/command-line/init/init-v2.js +1 -1
  9. package/src/command-line/nx-commands.js +3 -0
  10. package/src/command-line/release/changelog.js +80 -42
  11. package/src/command-line/release/config/version-plans.d.ts +5 -0
  12. package/src/command-line/release/config/version-plans.js +9 -5
  13. package/src/command-line/release/plan.js +25 -45
  14. package/src/command-line/release/utils/generate-version-plan-content.js +2 -3
  15. package/src/command-line/release/version.d.ts +5 -0
  16. package/src/command-line/sync/command-object.d.ts +6 -0
  17. package/src/command-line/sync/command-object.js +25 -0
  18. package/src/command-line/sync/sync.d.ts +6 -0
  19. package/src/command-line/sync/sync.js +30 -0
  20. package/src/config/nx-json.d.ts +23 -0
  21. package/src/config/workspace-json-project-json.d.ts +5 -0
  22. package/src/core/graph/main.js +1 -1
  23. package/src/core/graph/styles.css +1 -1
  24. package/src/daemon/cache.d.ts +1 -0
  25. package/src/daemon/cache.js +25 -18
  26. package/src/daemon/client/client.d.ts +5 -0
  27. package/src/daemon/client/client.js +42 -1
  28. package/src/daemon/message-types/flush-sync-generator-changes-to-disk.d.ts +6 -0
  29. package/src/daemon/message-types/flush-sync-generator-changes-to-disk.js +11 -0
  30. package/src/daemon/message-types/force-shutdown.d.ts +5 -0
  31. package/src/daemon/message-types/force-shutdown.js +11 -0
  32. package/src/daemon/message-types/get-registered-sync-generators.d.ts +5 -0
  33. package/src/daemon/message-types/get-registered-sync-generators.js +11 -0
  34. package/src/daemon/message-types/get-sync-generator-changes.d.ts +6 -0
  35. package/src/daemon/message-types/get-sync-generator-changes.js +11 -0
  36. package/src/daemon/message-types/update-workspace-context.d.ts +8 -0
  37. package/src/daemon/message-types/update-workspace-context.js +11 -0
  38. package/src/daemon/server/handle-flush-sync-generator-changes-to-disk.d.ts +2 -0
  39. package/src/daemon/server/handle-flush-sync-generator-changes-to-disk.js +11 -0
  40. package/src/daemon/server/handle-force-shutdown.d.ts +5 -0
  41. package/src/daemon/server/handle-force-shutdown.js +18 -0
  42. package/src/daemon/server/handle-get-registered-sync-generators.d.ts +2 -0
  43. package/src/daemon/server/handle-get-registered-sync-generators.js +11 -0
  44. package/src/daemon/server/handle-get-sync-generator-changes.d.ts +2 -0
  45. package/src/daemon/server/handle-get-sync-generator-changes.js +17 -0
  46. package/src/daemon/server/handle-request-shutdown.js +2 -0
  47. package/src/daemon/server/handle-update-workspace-context.d.ts +2 -0
  48. package/src/daemon/server/handle-update-workspace-context.js +11 -0
  49. package/src/daemon/server/project-graph-incremental-recomputation.d.ts +1 -0
  50. package/src/daemon/server/project-graph-incremental-recomputation.js +19 -2
  51. package/src/daemon/server/server.d.ts +1 -0
  52. package/src/daemon/server/server.js +39 -0
  53. package/src/daemon/server/shutdown-utils.d.ts +2 -1
  54. package/src/daemon/server/shutdown-utils.js +11 -4
  55. package/src/daemon/server/sync-generators.d.ts +6 -0
  56. package/src/daemon/server/sync-generators.js +202 -0
  57. package/src/daemon/server/watcher.js +3 -0
  58. package/src/daemon/socket-utils.js +18 -5
  59. package/src/daemon/tmp-dir.js +2 -1
  60. package/src/native/nx.wasm32-wasi.wasm +0 -0
  61. package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +1 -1
  62. package/src/nx-cloud/models/onboarding-status.d.ts +1 -0
  63. package/src/nx-cloud/models/onboarding-status.js +2 -0
  64. package/src/nx-cloud/utilities/is-workspace-claimed.d.ts +1 -0
  65. package/src/nx-cloud/utilities/is-workspace-claimed.js +24 -0
  66. package/src/nx-cloud/utilities/onboarding.d.ts +5 -0
  67. package/src/nx-cloud/utilities/onboarding.js +28 -0
  68. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +7 -2
  69. package/src/project-graph/plugins/internal-api.js +16 -5
  70. package/src/project-graph/plugins/isolation/messaging.d.ts +5 -1
  71. package/src/project-graph/plugins/isolation/messaging.js +1 -0
  72. package/src/project-graph/plugins/isolation/plugin-pool.js +4 -6
  73. package/src/project-graph/plugins/isolation/plugin-worker.js +15 -0
  74. package/src/project-graph/utils/project-configuration-utils.js +5 -2
  75. package/src/tasks-runner/run-command.d.ts +1 -1
  76. package/src/tasks-runner/run-command.js +120 -2
  77. package/src/utils/package-manager.js +12 -3
  78. package/src/utils/plugins/output.js +1 -1
  79. package/src/utils/sync-generators.d.ts +22 -0
  80. package/src/utils/sync-generators.js +161 -0
  81. package/src/utils/workspace-context.d.ts +1 -0
  82. package/src/utils/workspace-context.js +16 -0
  83. package/src/daemon/message-types/update-context-files.d.ts +0 -7
  84. package/src/daemon/message-types/update-context-files.js +0 -11
@@ -53,3 +53,11 @@ function isMainNxPackage() {
53
53
  const thisNxPath = require.resolve('nx');
54
54
  return mainNxPath === thisNxPath;
55
55
  }
56
+ process.on('uncaughtException', (e) => {
57
+ logger_1.logger.verbose(e);
58
+ process.exit(0);
59
+ });
60
+ process.on('unhandledRejection', (e) => {
61
+ logger_1.logger.verbose(e);
62
+ process.exit(0);
63
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "19.6.0-beta.0",
3
+ "version": "19.6.0-beta.2",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -71,7 +71,7 @@
71
71
  "yargs-parser": "21.1.1",
72
72
  "node-machine-id": "1.1.12",
73
73
  "ora": "5.3.0",
74
- "@nrwl/tao": "19.6.0-beta.0"
74
+ "@nrwl/tao": "19.6.0-beta.2"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "@swc-node/register": "^1.8.0",
@@ -86,16 +86,16 @@
86
86
  }
87
87
  },
88
88
  "optionalDependencies": {
89
- "@nx/nx-darwin-x64": "19.6.0-beta.0",
90
- "@nx/nx-darwin-arm64": "19.6.0-beta.0",
91
- "@nx/nx-linux-x64-gnu": "19.6.0-beta.0",
92
- "@nx/nx-linux-x64-musl": "19.6.0-beta.0",
93
- "@nx/nx-win32-x64-msvc": "19.6.0-beta.0",
94
- "@nx/nx-linux-arm64-gnu": "19.6.0-beta.0",
95
- "@nx/nx-linux-arm64-musl": "19.6.0-beta.0",
96
- "@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.0",
97
- "@nx/nx-win32-arm64-msvc": "19.6.0-beta.0",
98
- "@nx/nx-freebsd-x64": "19.6.0-beta.0"
89
+ "@nx/nx-darwin-x64": "19.6.0-beta.2",
90
+ "@nx/nx-darwin-arm64": "19.6.0-beta.2",
91
+ "@nx/nx-linux-x64-gnu": "19.6.0-beta.2",
92
+ "@nx/nx-linux-x64-musl": "19.6.0-beta.2",
93
+ "@nx/nx-win32-x64-msvc": "19.6.0-beta.2",
94
+ "@nx/nx-linux-arm64-gnu": "19.6.0-beta.2",
95
+ "@nx/nx-linux-arm64-musl": "19.6.0-beta.2",
96
+ "@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.2",
97
+ "@nx/nx-win32-arm64-msvc": "19.6.0-beta.2",
98
+ "@nx/nx-freebsd-x64": "19.6.0-beta.2"
99
99
  },
100
100
  "nx-migrations": {
101
101
  "migrations": "./migrations.json",
@@ -216,13 +216,28 @@ function groupBy(items, key) {
216
216
  return groups;
217
217
  }
218
218
  function formatChange(change, changelogRenderOptions, repoSlug) {
219
+ let description = change.description;
220
+ let extraLines = [];
221
+ let extraLinesStr = '';
222
+ if (description.includes('\n')) {
223
+ [description, ...extraLines] = description.split('\n');
224
+ // Align the extra lines with the start of the description for better readability
225
+ const indentation = ' ';
226
+ extraLinesStr = extraLines
227
+ .filter((l) => l.trim().length > 0)
228
+ .map((l) => `${indentation}${l}`)
229
+ .join('\n');
230
+ }
219
231
  let changeLine = '- ' +
220
232
  (change.isBreaking ? '⚠️ ' : '') +
221
233
  (change.scope ? `**${change.scope.trim()}:** ` : '') +
222
- change.description;
234
+ description;
223
235
  if (repoSlug && changelogRenderOptions.commitReferences) {
224
236
  changeLine += (0, github_1.formatReferences)(change.githubReferences, repoSlug);
225
237
  }
238
+ if (extraLinesStr) {
239
+ changeLine += '\n\n' + extraLinesStr;
240
+ }
226
241
  return changeLine;
227
242
  }
228
243
  /**
@@ -246,6 +246,31 @@
246
246
  "type": "string"
247
247
  }
248
248
  }
249
+ },
250
+ "sync": {
251
+ "type": "object",
252
+ "description": "Configuration for the `nx sync` command",
253
+ "properties": {
254
+ "globalGenerators": {
255
+ "type": "array",
256
+ "items": {
257
+ "type": "string"
258
+ },
259
+ "description": "List of workspace-wide sync generators to be run (not attached to targets)"
260
+ },
261
+ "generatorOptions": {
262
+ "type": "object",
263
+ "description": "Options for the sync generators.",
264
+ "additionalProperties": {
265
+ "type": "object"
266
+ }
267
+ },
268
+ "applyChanges": {
269
+ "type": "boolean",
270
+ "description": "Whether to automatically apply sync generator changes when running tasks. If not set, the user will be prompted. If set to `true`, the user will not be prompted and the changes will be applied. If set to `false`, the user will not be prompted and the changes will not be applied."
271
+ }
272
+ },
273
+ "additionalProperties": false
249
274
  }
250
275
  },
251
276
  "definitions": {
@@ -153,6 +153,13 @@
153
153
  }
154
154
  },
155
155
  "additionalProperties": true
156
+ },
157
+ "syncGenerators": {
158
+ "type": "array",
159
+ "items": {
160
+ "type": "string"
161
+ },
162
+ "description": "List of generators to run before the target to ensure the workspace is up to date"
156
163
  }
157
164
  }
158
165
  }
@@ -1,2 +1,2 @@
1
1
  export declare const allowedProjectExtensions: readonly ["tags", "implicitDependencies", "configFilePath", "$schema", "generators", "namedInputs", "name", "files", "root", "sourceRoot", "projectType", "release", "includedScripts", "metadata"];
2
- export declare const allowedWorkspaceExtensions: readonly ["implicitDependencies", "affected", "defaultBase", "tasksRunnerOptions", "workspaceLayout", "plugins", "targetDefaults", "files", "generators", "namedInputs", "extends", "cli", "pluginsConfig", "defaultProject", "installation", "release", "nxCloudAccessToken", "nxCloudId", "nxCloudUrl", "nxCloudEncryptionKey", "parallel", "cacheDirectory", "useDaemonProcess", "useInferencePlugins", "neverConnectToCloud"];
2
+ export declare const allowedWorkspaceExtensions: readonly ["implicitDependencies", "affected", "defaultBase", "tasksRunnerOptions", "workspaceLayout", "plugins", "targetDefaults", "files", "generators", "namedInputs", "extends", "cli", "pluginsConfig", "defaultProject", "installation", "release", "nxCloudAccessToken", "nxCloudId", "nxCloudUrl", "nxCloudEncryptionKey", "parallel", "cacheDirectory", "useDaemonProcess", "useInferencePlugins", "neverConnectToCloud", "sync"];
@@ -62,6 +62,7 @@ exports.allowedWorkspaceExtensions = [
62
62
  'useDaemonProcess',
63
63
  'useInferencePlugins',
64
64
  'neverConnectToCloud',
65
+ 'sync',
65
66
  ];
66
67
  if (!patched) {
67
68
  Module.prototype.require = function () {
@@ -33,7 +33,7 @@ async function initHandler(options) {
33
33
  (0, add_nx_scripts_1.generateDotNxSetup)(version);
34
34
  const { plugins } = await detectPlugins();
35
35
  plugins.forEach((plugin) => {
36
- (0, child_process_2.execSync)(`./nx add ${plugin}`, {
36
+ (0, child_process_1.runNxSync)(`add ${plugin}`, {
37
37
  stdio: 'inherit',
38
38
  });
39
39
  });
@@ -24,6 +24,7 @@ const command_object_18 = require("./reset/command-object");
24
24
  const command_object_19 = require("./release/command-object");
25
25
  const command_object_20 = require("./add/command-object");
26
26
  const command_objects_1 = require("./deprecated/command-objects");
27
+ const command_object_21 = require("./sync/command-object");
27
28
  // Ensure that the output takes up the available width of the terminal.
28
29
  yargs.wrap(yargs.terminalWidth());
29
30
  exports.parserConfiguration = {
@@ -67,6 +68,8 @@ exports.commandsObject = yargs
67
68
  .command(command_object_14.yargsRunCommand)
68
69
  .command(command_object_15.yargsRunManyCommand)
69
70
  .command(command_object_16.yargsShowCommand)
71
+ .command(command_object_21.yargsSyncCommand)
72
+ .command(command_object_21.yargsSyncCheckCommand)
70
73
  .command(command_object_2.yargsViewLogsCommand)
71
74
  .command(command_object_17.yargsWatchCommand)
72
75
  .command(command_object_14.yargsNxInfixCommand)
@@ -146,23 +146,34 @@ function createAPI(overrideReleaseConfig) {
146
146
  const releaseGroup = releaseGroups[0];
147
147
  if (releaseGroup.projectsRelationship === 'fixed') {
148
148
  const versionPlans = releaseGroup.versionPlans;
149
- workspaceChangelogChanges = filterHiddenChanges(versionPlans
150
- .map((vp) => {
151
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
152
- // only properly formatted conventional commits messages will be included in the changelog
153
- if (!parsedMessage) {
154
- return null;
155
- }
156
- return {
157
- type: parsedMessage.type,
158
- scope: parsedMessage.scope,
159
- description: parsedMessage.description,
160
- body: '',
161
- isBreaking: parsedMessage.breaking,
162
- githubReferences: [],
163
- };
149
+ workspaceChangelogChanges = versionPlans
150
+ .flatMap((vp) => {
151
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
152
+ const changes = !vp.triggeredByProjects
153
+ ? {
154
+ type: releaseType.type,
155
+ scope: '',
156
+ description: vp.message,
157
+ body: '',
158
+ isBreaking: releaseType.isBreaking,
159
+ githubReferences: [],
160
+ affectedProjects: '*',
161
+ }
162
+ : vp.triggeredByProjects.map((project) => {
163
+ return {
164
+ type: releaseType.type,
165
+ scope: project,
166
+ description: vp.message,
167
+ body: '',
168
+ // TODO: what about github references?
169
+ isBreaking: releaseType.isBreaking,
170
+ githubReferences: [],
171
+ affectedProjects: [project],
172
+ };
173
+ });
174
+ return changes;
164
175
  })
165
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
176
+ .filter(Boolean);
166
177
  }
167
178
  }
168
179
  }
@@ -286,24 +297,25 @@ function createAPI(overrideReleaseConfig) {
286
297
  // TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
287
298
  let commits;
288
299
  if (releaseGroup.versionPlans) {
289
- changes = filterHiddenChanges(releaseGroup.versionPlans
300
+ changes = releaseGroup.versionPlans
290
301
  .map((vp) => {
291
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
292
- // only properly formatted conventional commits messages will be included in the changelog
293
- if (!parsedMessage) {
302
+ const bumpForProject = vp.projectVersionBumps[project.name];
303
+ if (!bumpForProject) {
294
304
  return null;
295
305
  }
306
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(bumpForProject);
296
307
  return {
297
- type: parsedMessage.type,
298
- scope: parsedMessage.scope,
299
- description: parsedMessage.description,
308
+ type: releaseType.type,
309
+ scope: project.name,
310
+ description: vp.message,
300
311
  body: '',
301
- isBreaking: parsedMessage.breaking,
312
+ isBreaking: releaseType.isBreaking,
302
313
  affectedProjects: Object.keys(vp.projectVersionBumps),
314
+ // TODO: can we include github references when using version plans?
303
315
  githubReferences: [],
304
316
  };
305
317
  })
306
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
318
+ .filter(Boolean);
307
319
  }
308
320
  else {
309
321
  let fromRef = args.from ||
@@ -385,24 +397,34 @@ function createAPI(overrideReleaseConfig) {
385
397
  // TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
386
398
  let commits = [];
387
399
  if (releaseGroup.versionPlans) {
388
- changes = filterHiddenChanges(releaseGroup.versionPlans
389
- .map((vp) => {
390
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
391
- // only properly formatted conventional commits messages will be included in the changelog
392
- if (!parsedMessage) {
393
- return null;
394
- }
395
- return {
396
- type: parsedMessage.type,
397
- scope: parsedMessage.scope,
398
- description: parsedMessage.description,
399
- body: '',
400
- isBreaking: parsedMessage.breaking,
401
- githubReferences: [],
402
- affectedProjects: '*',
403
- };
400
+ changes = releaseGroup.versionPlans
401
+ .flatMap((vp) => {
402
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
403
+ const changes = !vp.triggeredByProjects
404
+ ? {
405
+ type: releaseType.type,
406
+ scope: '',
407
+ description: vp.message,
408
+ body: '',
409
+ isBreaking: releaseType.isBreaking,
410
+ githubReferences: [],
411
+ affectedProjects: '*',
412
+ }
413
+ : vp.triggeredByProjects.map((project) => {
414
+ return {
415
+ type: releaseType.type,
416
+ scope: project,
417
+ description: vp.message,
418
+ body: '',
419
+ // TODO: what about github references?
420
+ isBreaking: releaseType.isBreaking,
421
+ githubReferences: [],
422
+ affectedProjects: [project],
423
+ };
424
+ });
425
+ return changes;
404
426
  })
405
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
427
+ .filter(Boolean);
406
428
  }
407
429
  else {
408
430
  let fromRef = args.from ||
@@ -914,3 +936,19 @@ function createFileToProjectMap(projectFileMap) {
914
936
  }
915
937
  return fileToProjectMap;
916
938
  }
939
+ function versionPlanSemverReleaseTypeToChangelogType(bump) {
940
+ switch (bump) {
941
+ case 'premajor':
942
+ case 'major':
943
+ return { type: 'feat', isBreaking: true };
944
+ case 'preminor':
945
+ case 'minor':
946
+ return { type: 'feat', isBreaking: false };
947
+ case 'prerelease':
948
+ case 'prepatch':
949
+ case 'patch':
950
+ return { type: 'fix', isBreaking: false };
951
+ default:
952
+ throw new Error(`Invalid semver bump type: ${bump}`);
953
+ }
954
+ }
@@ -15,6 +15,11 @@ export interface VersionPlan extends VersionPlanFile {
15
15
  }
16
16
  export interface GroupVersionPlan extends VersionPlan {
17
17
  groupVersionBump: ReleaseType;
18
+ /**
19
+ * Will not be set if the group name was the trigger, otherwise will be a list of
20
+ * all the individual project names explicitly found in the version plan file.
21
+ */
22
+ triggeredByProjects?: string[];
18
23
  }
19
24
  export interface ProjectsVersionPlan extends VersionPlan {
20
25
  projectVersionBumps: Record<string, ReleaseType>;
@@ -29,7 +29,7 @@ async function readRawVersionPlans() {
29
29
  relativePath: (0, path_1.join)(versionPlansDirectory, versionPlanFile),
30
30
  fileName: versionPlanFile,
31
31
  content: parsedContent.attributes,
32
- message: getSingleLineMessage(parsedContent.body),
32
+ message: parsedContent.body,
33
33
  createdOnMs: versionPlanStats.birthtimeMs,
34
34
  });
35
35
  }
@@ -39,6 +39,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
39
39
  const groupsByName = releaseGroups.reduce((acc, group) => acc.set(group.name, group), new Map());
40
40
  const isDefaultGroup = isDefault(releaseGroups);
41
41
  for (const rawVersionPlan of rawVersionPlans) {
42
+ if (!rawVersionPlan.message) {
43
+ throw new Error(`Please add a changelog message to version plan: '${rawVersionPlan.fileName}'`);
44
+ }
42
45
  for (const [key, value] of Object.entries(rawVersionPlan.content)) {
43
46
  if (groupsByName.has(key)) {
44
47
  const group = groupsByName.get(key);
@@ -143,6 +146,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
143
146
  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.`);
144
147
  }
145
148
  }
149
+ else {
150
+ existingPlan.triggeredByProjects.push(key);
151
+ }
146
152
  }
147
153
  else {
148
154
  groupForProject.versionPlans.push({
@@ -152,7 +158,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
152
158
  createdOnMs: rawVersionPlan.createdOnMs,
153
159
  message: rawVersionPlan.message,
154
160
  // This is a fixed group, so the version bump is for the group, even if a project within it was specified
161
+ // but we track the projects that triggered the version bump so that we can accurately produce changelog entries.
155
162
  groupVersionBump: value,
163
+ triggeredByProjects: [key],
156
164
  });
157
165
  }
158
166
  }
@@ -177,7 +185,3 @@ function getVersionPlansAbsolutePath() {
177
185
  function isReleaseType(value) {
178
186
  return semver_1.RELEASE_TYPES.includes(value);
179
187
  }
180
- // changelog messages may only be a single line long, so ignore anything else
181
- function getSingleLineMessage(message) {
182
- return message.trim().split('\n')[0];
183
- }
@@ -4,21 +4,22 @@ exports.releasePlanCLIHandler = void 0;
4
4
  exports.createAPI = createAPI;
5
5
  const enquirer_1 = require("enquirer");
6
6
  const fs_extra_1 = require("fs-extra");
7
- const path_1 = require("path");
7
+ const node_path_1 = require("node:path");
8
8
  const semver_1 = require("semver");
9
+ const tmp_1 = require("tmp");
9
10
  const nx_json_1 = require("../../config/nx-json");
10
11
  const file_map_utils_1 = require("../../project-graph/file-map-utils");
11
12
  const project_graph_1 = require("../../project-graph/project-graph");
12
13
  const output_1 = require("../../utils/output");
13
14
  const params_1 = require("../../utils/params");
14
15
  const config_1 = require("./config/config");
16
+ const deep_merge_json_1 = require("./config/deep-merge-json");
15
17
  const filter_release_groups_1 = require("./config/filter-release-groups");
16
18
  const version_plans_1 = require("./config/version-plans");
17
19
  const generate_version_plan_content_1 = require("./utils/generate-version-plan-content");
18
- const git_1 = require("./utils/git");
20
+ const launch_editor_1 = require("./utils/launch-editor");
19
21
  const print_changes_1 = require("./utils/print-changes");
20
22
  const print_config_1 = require("./utils/print-config");
21
- const deep_merge_json_1 = require("./config/deep-merge-json");
22
23
  const releasePlanCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => createAPI({})(args));
23
24
  exports.releasePlanCLIHandler = releasePlanCLIHandler;
24
25
  function createAPI(overrideReleaseConfig) {
@@ -53,25 +54,6 @@ function createAPI(overrideReleaseConfig) {
53
54
  versionPlanBumps[projectOrGroup] = version;
54
55
  }
55
56
  };
56
- if (args.message) {
57
- const message = (0, git_1.parseConventionalCommitsMessage)(args.message);
58
- if (!message) {
59
- output_1.output.error({
60
- title: 'Changelog message is not in conventional commits format.',
61
- bodyLines: [
62
- 'Please ensure your message is in the form of:',
63
- ' type(optional scope): description',
64
- '',
65
- 'For example:',
66
- ' feat(pkg-b): add new feature',
67
- ' fix(pkg-a): correct a bug',
68
- ' chore: update build process',
69
- ' fix(core)!: breaking change in core package',
70
- ],
71
- });
72
- process.exit(1);
73
- }
74
- }
75
57
  if (releaseGroups[0].name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
76
58
  const group = releaseGroups[0];
77
59
  if (group.projectsRelationship === 'independent') {
@@ -106,9 +88,10 @@ function createAPI(overrideReleaseConfig) {
106
88
  });
107
89
  return 0;
108
90
  }
109
- const versionPlanMessage = args.message || (await promptForMessage());
91
+ const versionPlanName = `version-plan-${new Date().getTime()}`;
92
+ const versionPlanMessage = args.message || (await promptForMessage(versionPlanName));
110
93
  const versionPlanFileContent = (0, generate_version_plan_content_1.generateVersionPlanContent)(versionPlanBumps, versionPlanMessage);
111
- const versionPlanFileName = `version-plan-${new Date().getTime()}.md`;
94
+ const versionPlanFileName = `${versionPlanName}.md`;
112
95
  if (args.dryRun) {
113
96
  output_1.output.logSingleLine(`Would create version plan file "${versionPlanFileName}", but --dry-run was set.`);
114
97
  (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
@@ -118,7 +101,7 @@ function createAPI(overrideReleaseConfig) {
118
101
  (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
119
102
  const versionPlansAbsolutePath = (0, version_plans_1.getVersionPlansAbsolutePath)();
120
103
  await (0, fs_extra_1.ensureDir)(versionPlansAbsolutePath);
121
- await (0, fs_extra_1.writeFile)((0, path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
104
+ await (0, fs_extra_1.writeFile)((0, node_path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
122
105
  }
123
106
  return 0;
124
107
  };
@@ -142,41 +125,38 @@ async function promptForVersion(message) {
142
125
  process.exit(0);
143
126
  }
144
127
  }
145
- async function promptForMessage() {
128
+ async function promptForMessage(versionPlanName) {
146
129
  let message;
147
130
  do {
148
- message = await _promptForMessage();
131
+ message = await _promptForMessage(versionPlanName);
149
132
  } while (!message);
150
133
  return message;
151
134
  }
152
- // TODO: support non-conventional commits messages (will require significant changelog renderer changes)
153
- async function _promptForMessage() {
135
+ async function _promptForMessage(versionPlanName) {
154
136
  try {
155
137
  const reply = await (0, enquirer_1.prompt)([
156
138
  {
157
139
  name: 'message',
158
- message: 'What changelog message would you like associated with this change?',
140
+ message: 'What changelog message would you like associated with this change? (Leave blank to open an external editor for multi-line messages/easier editing)',
159
141
  type: 'input',
160
142
  },
161
143
  ]);
162
- const conventionalCommitsMessage = (0, git_1.parseConventionalCommitsMessage)(reply.message);
163
- if (!conventionalCommitsMessage) {
144
+ let message = reply.message.trim();
145
+ if (!message.length) {
146
+ const tmpDir = (0, tmp_1.dirSync)().name;
147
+ const messageFilePath = (0, node_path_1.join)(tmpDir, `DRAFT_MESSAGE__${versionPlanName}.md`);
148
+ (0, fs_extra_1.writeFileSync)(messageFilePath, '');
149
+ await (0, launch_editor_1.launchEditor)(messageFilePath);
150
+ message = (0, fs_extra_1.readFileSync)(messageFilePath, 'utf-8');
151
+ }
152
+ message = message.trim();
153
+ if (!message) {
164
154
  output_1.output.warn({
165
- title: 'Changelog message is not in conventional commits format.',
166
- bodyLines: [
167
- 'Please ensure your message is in the form of:',
168
- ' type(optional scope): description',
169
- '',
170
- 'For example:',
171
- ' feat(pkg-b): add new feature',
172
- ' fix(pkg-a): correct a bug',
173
- ' chore: update build process',
174
- ' fix(core)!: breaking change in core package',
175
- ],
155
+ title: 'A changelog message is required in order to create the version plan file',
156
+ bodyLines: [],
176
157
  });
177
- return null;
178
158
  }
179
- return reply.message;
159
+ return message;
180
160
  }
181
161
  catch (e) {
182
162
  output_1.output.log({
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateVersionPlanContent = generateVersionPlanContent;
4
4
  function generateVersionPlanContent(bumps, message) {
5
- return `---
5
+ const frontMatter = `---
6
6
  ${Object.entries(bumps)
7
7
  .filter(([_, version]) => version !== 'none')
8
8
  .map(([projectOrGroup, version]) => {
@@ -15,7 +15,6 @@ ${Object.entries(bumps)
15
15
  })
16
16
  .join('\n')}
17
17
  ---
18
-
19
- ${message}
20
18
  `;
19
+ return `${frontMatter}${message ? `\n${message}\n` : ''}`;
21
20
  }
@@ -30,6 +30,11 @@ export interface ReleaseVersionGeneratorSchema {
30
30
  * This is only applicable to independently released projects.
31
31
  */
32
32
  updateDependents?: 'never' | 'auto';
33
+ /**
34
+ * Whether or not to completely omit project logs when that project has no applicable changes. This can be useful for
35
+ * large monorepos which have a large number of projects, especially when only a subset are released together.
36
+ */
37
+ logUnchangedProjects?: boolean;
33
38
  }
34
39
  export interface NxReleaseVersionResult {
35
40
  /**
@@ -0,0 +1,6 @@
1
+ import type { CommandModule } from 'yargs';
2
+ export interface SyncArgs {
3
+ verbose?: boolean;
4
+ }
5
+ export declare const yargsSyncCommand: CommandModule<Record<string, unknown>, SyncArgs>;
6
+ export declare const yargsSyncCheckCommand: CommandModule<Record<string, unknown>, SyncArgs>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.yargsSyncCheckCommand = exports.yargsSyncCommand = void 0;
4
+ exports.yargsSyncCommand = {
5
+ command: 'sync',
6
+ describe: false,
7
+ builder: (yargs) => yargs.option('verbose', {
8
+ type: 'boolean',
9
+ description: 'Prints additional information about the commands (e.g., stack traces)',
10
+ }),
11
+ handler: async (args) => {
12
+ process.exit(await Promise.resolve().then(() => require('./sync')).then((m) => m.syncHandler(args)));
13
+ },
14
+ };
15
+ exports.yargsSyncCheckCommand = {
16
+ command: 'sync:check',
17
+ describe: false,
18
+ builder: (yargs) => yargs.option('verbose', {
19
+ type: 'boolean',
20
+ description: 'Prints additional information about the commands (e.g., stack traces)',
21
+ }),
22
+ handler: async (args) => {
23
+ process.exit(await Promise.resolve().then(() => require('./sync')).then((m) => m.syncHandler({ ...args, check: true })));
24
+ },
25
+ };
@@ -0,0 +1,6 @@
1
+ import type { SyncArgs } from './command-object';
2
+ interface SyncOptions extends SyncArgs {
3
+ check?: boolean;
4
+ }
5
+ export declare function syncHandler(options: SyncOptions): Promise<number>;
6
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncHandler = syncHandler;
4
+ const project_graph_1 = require("../../project-graph/project-graph");
5
+ const output_1 = require("../../utils/output");
6
+ const params_1 = require("../../utils/params");
7
+ const sync_generators_1 = require("../../utils/sync-generators");
8
+ function syncHandler(options) {
9
+ if (options.verbose) {
10
+ process.env.NX_VERBOSE_LOGGING = 'true';
11
+ }
12
+ const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true';
13
+ return (0, params_1.handleErrors)(isVerbose, async () => {
14
+ const projectGraph = await (0, project_graph_1.createProjectGraphAsync)();
15
+ const syncGenerators = await (0, sync_generators_1.collectAllRegisteredSyncGenerators)(projectGraph);
16
+ const results = await (0, sync_generators_1.getSyncGeneratorChanges)(syncGenerators);
17
+ if (!results.length) {
18
+ return 0;
19
+ }
20
+ if (options.check) {
21
+ output_1.output.error({
22
+ title: `The workspace is out of sync`,
23
+ bodyLines: (0, sync_generators_1.syncGeneratorResultsToMessageLines)(results),
24
+ });
25
+ return 1;
26
+ }
27
+ await (0, sync_generators_1.flushSyncGeneratorChanges)(results);
28
+ return 0;
29
+ });
30
+ }