nx 19.6.0-beta.0 → 19.6.0-beta.1

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 (39) hide show
  1. package/package.json +12 -12
  2. package/release/changelog-renderer/index.js +16 -1
  3. package/src/command-line/init/init-v2.js +1 -1
  4. package/src/command-line/release/changelog.js +80 -42
  5. package/src/command-line/release/config/version-plans.d.ts +5 -0
  6. package/src/command-line/release/config/version-plans.js +9 -5
  7. package/src/command-line/release/plan.js +25 -45
  8. package/src/command-line/release/utils/generate-version-plan-content.js +2 -3
  9. package/src/command-line/release/version.d.ts +5 -0
  10. package/src/core/graph/main.js +1 -1
  11. package/src/core/graph/styles.css +1 -1
  12. package/src/daemon/cache.d.ts +1 -0
  13. package/src/daemon/cache.js +25 -18
  14. package/src/daemon/client/client.js +9 -1
  15. package/src/daemon/message-types/force-shutdown.d.ts +5 -0
  16. package/src/daemon/message-types/force-shutdown.js +11 -0
  17. package/src/daemon/server/handle-force-shutdown.d.ts +5 -0
  18. package/src/daemon/server/handle-force-shutdown.js +18 -0
  19. package/src/daemon/server/handle-request-shutdown.js +2 -0
  20. package/src/daemon/server/server.d.ts +1 -0
  21. package/src/daemon/server/server.js +14 -0
  22. package/src/daemon/server/shutdown-utils.d.ts +2 -1
  23. package/src/daemon/server/shutdown-utils.js +11 -4
  24. package/src/daemon/server/watcher.js +3 -0
  25. package/src/native/nx.wasm32-wasi.wasm +0 -0
  26. package/src/nx-cloud/models/onboarding-status.d.ts +1 -0
  27. package/src/nx-cloud/models/onboarding-status.js +2 -0
  28. package/src/nx-cloud/utilities/is-workspace-claimed.d.ts +1 -0
  29. package/src/nx-cloud/utilities/is-workspace-claimed.js +24 -0
  30. package/src/nx-cloud/utilities/onboarding.d.ts +5 -0
  31. package/src/nx-cloud/utilities/onboarding.js +28 -0
  32. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +7 -2
  33. package/src/project-graph/plugins/internal-api.js +16 -5
  34. package/src/project-graph/plugins/isolation/messaging.d.ts +5 -1
  35. package/src/project-graph/plugins/isolation/messaging.js +1 -0
  36. package/src/project-graph/plugins/isolation/plugin-pool.js +4 -6
  37. package/src/project-graph/plugins/isolation/plugin-worker.js +15 -0
  38. package/src/project-graph/utils/project-configuration-utils.js +5 -2
  39. package/src/utils/package-manager.js +12 -3
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.1",
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.1"
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.1",
90
+ "@nx/nx-darwin-arm64": "19.6.0-beta.1",
91
+ "@nx/nx-linux-x64-gnu": "19.6.0-beta.1",
92
+ "@nx/nx-linux-x64-musl": "19.6.0-beta.1",
93
+ "@nx/nx-win32-x64-msvc": "19.6.0-beta.1",
94
+ "@nx/nx-linux-arm64-gnu": "19.6.0-beta.1",
95
+ "@nx/nx-linux-arm64-musl": "19.6.0-beta.1",
96
+ "@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.1",
97
+ "@nx/nx-win32-arm64-msvc": "19.6.0-beta.1",
98
+ "@nx/nx-freebsd-x64": "19.6.0-beta.1"
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
  /**
@@ -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
  });
@@ -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
  /**