nx 17.0.1 → 17.0.3

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 (41) hide show
  1. package/changelog-renderer/index.d.ts +43 -0
  2. package/changelog-renderer/index.js +180 -0
  3. package/package.json +12 -13
  4. package/schemas/nx-schema.json +141 -0
  5. package/src/adapter/ngcli-adapter.js +32 -0
  6. package/src/command-line/init/implementation/add-nx-to-monorepo.js +1 -0
  7. package/src/command-line/init/implementation/add-nx-to-nest.js +1 -0
  8. package/src/command-line/init/implementation/add-nx-to-npm-repo.js +1 -0
  9. package/src/command-line/init/implementation/utils.d.ts +1 -0
  10. package/src/command-line/init/implementation/utils.js +14 -1
  11. package/src/command-line/release/changelog.js +332 -75
  12. package/src/command-line/release/command-object.d.ts +1 -3
  13. package/src/command-line/release/command-object.js +3 -17
  14. package/src/command-line/release/config/config.d.ts +1 -1
  15. package/src/command-line/release/config/config.js +153 -50
  16. package/src/command-line/release/utils/markdown.d.ts +1 -4
  17. package/src/command-line/release/utils/markdown.js +3 -136
  18. package/src/command-line/release/utils/print-changes.d.ts +5 -1
  19. package/src/command-line/release/utils/print-changes.js +3 -2
  20. package/src/command-line/show/show.js +2 -0
  21. package/src/config/nx-json.d.ts +80 -3
  22. package/src/config/nx-json.js +1 -1
  23. package/src/config/project-graph.d.ts +1 -1
  24. package/src/daemon/client/client.js +0 -6
  25. package/src/daemon/server/outputs-tracking.d.ts +2 -2
  26. package/src/daemon/server/outputs-tracking.js +2 -2
  27. package/src/daemon/server/project-graph-incremental-recomputation.js +1 -28
  28. package/src/daemon/server/server.js +22 -58
  29. package/src/daemon/server/shutdown-utils.d.ts +0 -6
  30. package/src/daemon/server/shutdown-utils.js +1 -36
  31. package/src/daemon/server/watcher.d.ts +2 -6
  32. package/src/daemon/server/watcher.js +1 -92
  33. package/src/generators/utils/project-configuration.js +10 -8
  34. package/src/migrations/update-15-0-0/prefix-outputs.js +9 -9
  35. package/src/project-graph/project-graph.js +6 -1
  36. package/src/project-graph/utils/normalize-project-nodes.js +4 -1
  37. package/src/project-graph/utils/retrieve-workspace-files.js +3 -1
  38. package/src/tasks-runner/utils.js +8 -4
  39. package/src/utils/package-manager.d.ts +1 -0
  40. package/src/utils/package-manager.js +5 -2
  41. package/src/utils/params.js +19 -4
@@ -10,53 +10,88 @@ exports.CATCH_ALL_RELEASE_GROUP = '__default__';
10
10
  async function createNxReleaseConfig(projectGraph, userConfig = {},
11
11
  // Optionally ensure that all configured projects have implemented a certain target
12
12
  requiredTargetName) {
13
- const DEFAULT_VERSION_GENERATOR = '@nx/js:release-version';
14
- const DEFAULT_VERSION_GENERATOR_OPTIONS = {};
15
- const allProjects = (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes);
16
- const userSpecifiedGroups = userConfig.groups || {};
13
+ const WORKSPACE_DEFAULTS = {
14
+ version: {
15
+ generator: '@nx/js:release-version',
16
+ generatorOptions: {},
17
+ },
18
+ changelog: {
19
+ workspaceChangelog: {
20
+ createRelease: false,
21
+ entryWhenNoChanges: 'This was a version bump only, there were no code changes.',
22
+ file: '{workspaceRoot}/CHANGELOG.md',
23
+ renderer: 'nx/changelog-renderer',
24
+ renderOptions: {
25
+ includeAuthors: true,
26
+ },
27
+ },
28
+ // For projectChangelogs if the user has set any changelog config at all, then use one set of defaults, otherwise default to false for the whole feature
29
+ projectChangelogs: userConfig.changelog?.projectChangelogs
30
+ ? {
31
+ createRelease: false,
32
+ file: '{projectRoot}/CHANGELOG.md',
33
+ entryWhenNoChanges: 'This was a version bump only for {projectName} to align it with other projects, there were no code changes.',
34
+ renderer: 'nx/changelog-renderer',
35
+ renderOptions: {
36
+ includeAuthors: true,
37
+ },
38
+ }
39
+ : false,
40
+ },
41
+ releaseTagPattern: 'v{version}',
42
+ };
43
+ const GROUP_DEFAULTS = {
44
+ version: {
45
+ generator: '@nx/js:release-version',
46
+ generatorOptions: {},
47
+ },
48
+ changelog: {
49
+ createRelease: false,
50
+ entryWhenNoChanges: 'This was a version bump only for {projectName} to align it with other projects, there were no code changes.',
51
+ file: '{projectRoot}/CHANGELOG.md',
52
+ renderer: 'nx/changelog-renderer',
53
+ renderOptions: {
54
+ includeAuthors: true,
55
+ },
56
+ },
57
+ releaseTagPattern: '{projectName}@v{version}',
58
+ };
17
59
  /**
18
- * No user specified release groups, so we treat all projects as being in one release group
19
- * together in which all projects are released in lock step.
60
+ * We first process root level config and apply defaults, so that we know how to handle the group level
61
+ * overrides, if applicable.
20
62
  */
21
- if (Object.keys(userSpecifiedGroups).length === 0) {
22
- // Ensure all projects have the relevant target available, if applicable
23
- if (requiredTargetName) {
24
- const error = ensureProjectsHaveTarget(allProjects, projectGraph, requiredTargetName);
25
- if (error) {
26
- return {
27
- error,
28
- nxReleaseConfig: null,
29
- };
30
- }
31
- }
32
- return {
33
- error: null,
34
- nxReleaseConfig: {
35
- groups: {
36
- [exports.CATCH_ALL_RELEASE_GROUP]: {
37
- projects: allProjects,
38
- version: {
39
- generator: DEFAULT_VERSION_GENERATOR,
40
- generatorOptions: DEFAULT_VERSION_GENERATOR_OPTIONS,
41
- },
42
- },
63
+ const rootVersionConfig = deepMergeDefaults([WORKSPACE_DEFAULTS.version], userConfig.version);
64
+ const rootChangelogConfig = deepMergeDefaults([WORKSPACE_DEFAULTS.changelog], userConfig.changelog);
65
+ const allProjects = (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes);
66
+ const groups = userConfig.groups && Object.keys(userConfig.groups).length
67
+ ? ensureProjectsConfigIsArray(userConfig.groups)
68
+ : /**
69
+ * No user specified release groups, so we treat all projects as being in one release group
70
+ * together in which all projects are released in lock step.
71
+ */
72
+ {
73
+ [exports.CATCH_ALL_RELEASE_GROUP]: {
74
+ projects: allProjects,
75
+ /**
76
+ * For properties which are overriding config at the root, we use the root level config as the
77
+ * default values to merge with so that the group that matches a specific project will always
78
+ * be the valid source of truth for that type of config.
79
+ */
80
+ version: deepMergeDefaults([GROUP_DEFAULTS.version], rootVersionConfig),
81
+ releaseTagPattern: GROUP_DEFAULTS.releaseTagPattern,
82
+ // Directly inherit the root level config for projectChangelogs, if set
83
+ changelog: rootChangelogConfig.projectChangelogs || false,
43
84
  },
44
- },
45
- };
46
- }
85
+ };
47
86
  /**
48
- * The user has specified at least one release group.
49
- *
50
87
  * Resolve all the project names into their release groups, and check
51
88
  * that individual projects are not found in multiple groups.
52
89
  */
53
90
  const releaseGroups = {};
54
91
  const alreadyMatchedProjects = new Set();
55
- for (const [releaseGroupName, userSpecifiedGroup] of Object.entries(userSpecifiedGroups)) {
56
- // Ensure that the user config for the release group can resolve at least one project
57
- const matchingProjects = (0, find_matching_projects_1.findMatchingProjects)(Array.isArray(userSpecifiedGroup.projects)
58
- ? userSpecifiedGroup.projects
59
- : [userSpecifiedGroup.projects], projectGraph.nodes);
92
+ for (const [releaseGroupName, releaseGroup] of Object.entries(groups)) {
93
+ // Ensure that the config for the release group can resolve at least one project
94
+ const matchingProjects = (0, find_matching_projects_1.findMatchingProjects)(releaseGroup.projects, projectGraph.nodes);
60
95
  if (!matchingProjects.length) {
61
96
  return {
62
97
  error: {
@@ -92,25 +127,35 @@ requiredTargetName) {
92
127
  }
93
128
  alreadyMatchedProjects.add(project);
94
129
  }
95
- releaseGroups[releaseGroupName] = {
130
+ // First apply any group level defaults, then apply actual root level config (if applicable), then group level config
131
+ const groupChangelogDefaults = [GROUP_DEFAULTS.changelog];
132
+ if (rootChangelogConfig.projectChangelogs) {
133
+ groupChangelogDefaults.push(rootChangelogConfig.projectChangelogs);
134
+ }
135
+ const groupDefaults = {
96
136
  projects: matchingProjects,
97
- version: userSpecifiedGroup.version
98
- ? {
99
- generator: userSpecifiedGroup.version.generator || DEFAULT_VERSION_GENERATOR,
100
- generatorOptions: userSpecifiedGroup.version.generatorOptions ||
101
- DEFAULT_VERSION_GENERATOR_OPTIONS,
102
- }
103
- : {
104
- generator: DEFAULT_VERSION_GENERATOR,
105
- generatorOptions: DEFAULT_VERSION_GENERATOR_OPTIONS,
106
- },
137
+ version: deepMergeDefaults(
138
+ // First apply any group level defaults, then apply actual root level config, then group level config
139
+ [GROUP_DEFAULTS.version, rootVersionConfig], releaseGroup.version),
140
+ // If the user has set any changelog config at all, including at the root level, then use one set of defaults, otherwise default to false for the whole feature
141
+ changelog: releaseGroup.changelog || rootChangelogConfig.projectChangelogs
142
+ ? deepMergeDefaults(groupChangelogDefaults, releaseGroup.changelog || {})
143
+ : false,
144
+ releaseTagPattern: GROUP_DEFAULTS.releaseTagPattern,
107
145
  };
146
+ releaseGroups[releaseGroupName] = deepMergeDefaults([groupDefaults], {
147
+ ...releaseGroup,
148
+ // Ensure that the resolved project names take priority over the original user config (which could have contained unresolved globs etc)
149
+ projects: matchingProjects,
150
+ });
108
151
  }
109
152
  return {
110
153
  error: null,
111
154
  nxReleaseConfig: {
112
- ...userConfig,
155
+ version: rootVersionConfig,
156
+ changelog: rootChangelogConfig,
113
157
  groups: releaseGroups,
158
+ releaseTagPattern: userConfig.releaseTagPattern || WORKSPACE_DEFAULTS.releaseTagPattern,
114
159
  },
115
160
  };
116
161
  }
@@ -155,6 +200,18 @@ async function handleNxReleaseConfigError(error) {
155
200
  process.exit(1);
156
201
  }
157
202
  exports.handleNxReleaseConfigError = handleNxReleaseConfigError;
203
+ function ensureProjectsConfigIsArray(groups) {
204
+ const result = {};
205
+ for (const [groupName, groupConfig] of Object.entries(groups)) {
206
+ result[groupName] = {
207
+ ...groupConfig,
208
+ projects: Array.isArray(groupConfig.projects)
209
+ ? groupConfig.projects
210
+ : [groupConfig.projects],
211
+ };
212
+ }
213
+ return result;
214
+ }
158
215
  function ensureProjectsHaveTarget(projects, projectGraph, requiredTargetName) {
159
216
  const missingTargetProjects = projects.filter((project) => !(0, project_graph_utils_1.projectHasTarget)(projectGraph.nodes[project], requiredTargetName));
160
217
  if (missingTargetProjects.length) {
@@ -168,3 +225,49 @@ function ensureProjectsHaveTarget(projects, projectGraph, requiredTargetName) {
168
225
  }
169
226
  return null;
170
227
  }
228
+ function isObject(value) {
229
+ return value && typeof value === 'object' && !Array.isArray(value);
230
+ }
231
+ // Helper function to merge two config objects
232
+ function mergeConfig(objA, objB) {
233
+ const merged = { ...objA };
234
+ for (const key in objB) {
235
+ if (objB.hasOwnProperty(key)) {
236
+ // If objB[key] is explicitly set to false, null or 0, respect that value
237
+ if (objB[key] === false || objB[key] === null || objB[key] === 0) {
238
+ merged[key] = objB[key];
239
+ }
240
+ // If both objA[key] and objB[key] are objects, recursively merge them
241
+ else if (isObject(merged[key]) && isObject(objB[key])) {
242
+ merged[key] = mergeConfig(merged[key], objB[key]);
243
+ }
244
+ // If objB[key] is defined, use it (this will overwrite any existing value in merged[key])
245
+ else if (objB[key] !== undefined) {
246
+ merged[key] = objB[key];
247
+ }
248
+ }
249
+ }
250
+ return merged;
251
+ }
252
+ /**
253
+ * This function takes in a strictly typed collection of all possible default values in a particular section of config,
254
+ * and an optional set of partial user config, and returns a single, deeply merged config object, where the user
255
+ * config takes priority over the defaults in all cases (only an `undefined` value in the user config will be
256
+ * overwritten by the defaults, all other falsey values from the user will be respected).
257
+ */
258
+ function deepMergeDefaults(defaultConfigs, userConfig) {
259
+ let result;
260
+ // First merge defaultConfigs sequentially (meaning later defaults will override earlier ones)
261
+ for (const defaultConfig of defaultConfigs) {
262
+ if (!result) {
263
+ result = defaultConfig;
264
+ continue;
265
+ }
266
+ result = mergeConfig(result, defaultConfig);
267
+ }
268
+ // Finally, merge the userConfig
269
+ if (userConfig) {
270
+ result = mergeConfig(result, userConfig);
271
+ }
272
+ return result;
273
+ }
@@ -1,7 +1,4 @@
1
- import { GitCommit } from './git';
2
- import { RepoSlug } from './github';
3
- export declare function generateMarkdown(commits: GitCommit[], releaseVersion: string, repoSlug?: RepoSlug): Promise<string>;
4
- export declare function parseChangelogMarkdown(contents: string, tagVersionPrefix: any): {
1
+ export declare function parseChangelogMarkdown(contents: string): {
5
2
  releases: {
6
3
  version?: string;
7
4
  body: string;
@@ -1,141 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseChangelogMarkdown = exports.generateMarkdown = void 0;
4
- const github_1 = require("./github");
5
- // axios types and values don't seem to match
6
- const _axios = require("axios");
7
- const axios = _axios;
8
- function formatName(name = '') {
9
- return name
10
- .split(' ')
11
- .map((p) => p.trim())
12
- .join(' ');
13
- }
14
- function groupBy(items, key) {
15
- const groups = {};
16
- for (const item of items) {
17
- groups[item[key]] = groups[item[key]] || [];
18
- groups[item[key]].push(item);
19
- }
20
- return groups;
21
- }
22
- function formatCommit(commit, repoSlug) {
23
- let commitLine = '- ' +
24
- (commit.scope ? `**${commit.scope.trim()}:** ` : '') +
25
- (commit.isBreaking ? '⚠️ ' : '') +
26
- commit.description;
27
- if (repoSlug) {
28
- commitLine += (0, github_1.formatReferences)(commit.references, repoSlug);
29
- }
30
- return commitLine;
31
- }
32
- // TODO: allow this to be configurable via config in a future release
33
- async function generateMarkdown(commits, releaseVersion, repoSlug) {
34
- const typeGroups = groupBy(commits, 'type');
35
- const markdown = [];
36
- const breakingChanges = [];
37
- const commitTypes = {
38
- feat: { title: '🚀 Features' },
39
- perf: { title: '🔥 Performance' },
40
- fix: { title: '🩹 Fixes' },
41
- refactor: { title: '💅 Refactors' },
42
- docs: { title: '📖 Documentation' },
43
- build: { title: '📦 Build' },
44
- types: { title: '🌊 Types' },
45
- chore: { title: '🏡 Chore' },
46
- examples: { title: '🏀 Examples' },
47
- test: { title: '✅ Tests' },
48
- style: { title: '🎨 Styles' },
49
- ci: { title: '🤖 CI' },
50
- };
51
- // Version Title
52
- markdown.push('', `## ${releaseVersion}`, '');
53
- for (const type of Object.keys(commitTypes)) {
54
- const group = typeGroups[type];
55
- if (!group || group.length === 0) {
56
- continue;
57
- }
58
- markdown.push('', '### ' + commitTypes[type].title, '');
59
- /**
60
- * In order to make the final changelog most readable, we organize commits as follows:
61
- * - By scope, where scopes are in alphabetical order (commits with no scope are listed first)
62
- * - Within a particular scope grouping, we list commits in chronological order
63
- */
64
- const commitsInChronologicalOrder = group.reverse();
65
- const commitsGroupedByScope = groupBy(commitsInChronologicalOrder, 'scope');
66
- const scopesSortedAlphabetically = Object.keys(commitsGroupedByScope).sort();
67
- for (const scope of scopesSortedAlphabetically) {
68
- const commits = commitsGroupedByScope[scope];
69
- for (const commit of commits) {
70
- const line = formatCommit(commit, repoSlug);
71
- markdown.push(line);
72
- if (commit.isBreaking) {
73
- breakingChanges.push(line);
74
- }
75
- }
76
- }
77
- }
78
- if (breakingChanges.length > 0) {
79
- markdown.push('', '#### ⚠️ Breaking Changes', '', ...breakingChanges);
80
- }
81
- const _authors = new Map();
82
- for (const commit of commits) {
83
- if (!commit.author) {
84
- continue;
85
- }
86
- const name = formatName(commit.author.name);
87
- if (!name || name.includes('[bot]')) {
88
- continue;
89
- }
90
- if (_authors.has(name)) {
91
- const entry = _authors.get(name);
92
- entry.email.add(commit.author.email);
93
- }
94
- else {
95
- _authors.set(name, { email: new Set([commit.author.email]) });
96
- }
97
- }
98
- // Try to map authors to github usernames
99
- if (repoSlug) {
100
- await Promise.all([..._authors.keys()].map(async (authorName) => {
101
- const meta = _authors.get(authorName);
102
- for (const email of meta.email) {
103
- // For these pseudo-anonymized emails we can just extract the Github username from before the @
104
- if (email.endsWith('@users.noreply.github.com')) {
105
- meta.github = email.split('@')[0];
106
- break;
107
- }
108
- // Look up any other emails against the ungh.cc API
109
- const { data } = await axios
110
- .get(`https://ungh.cc/users/find/${email}`)
111
- .catch(() => ({ data: { user: null } }));
112
- if (data?.user) {
113
- meta.github = data.user.username;
114
- break;
115
- }
116
- }
117
- }));
118
- }
119
- const authors = [..._authors.entries()].map((e) => ({ name: e[0], ...e[1] }));
120
- if (authors.length > 0) {
121
- markdown.push('', '### ' + '❤️ Thank You', '', ...authors
122
- // Sort the contributors by name
123
- .sort((a, b) => a.name.localeCompare(b.name))
124
- .map((i) => {
125
- // Tag the author's Github username if we were able to resolve it so that Github adds them as a contributor
126
- const github = i.github ? ` @${i.github}` : '';
127
- return `- ${i.name}${github}`;
128
- }));
129
- }
130
- return markdown.join('\n').trim();
131
- }
132
- exports.generateMarkdown = generateMarkdown;
133
- function escapeRegExp(string) {
134
- return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
135
- }
136
- function parseChangelogMarkdown(contents, tagVersionPrefix) {
137
- const escapedTagVersionPrefix = escapeRegExp(tagVersionPrefix);
138
- const CHANGELOG_RELEASE_HEAD_RE = new RegExp('^#{2,}\\s+' + escapedTagVersionPrefix + '(\\d+\\.\\d+\\.\\d+)', 'gm');
3
+ exports.parseChangelogMarkdown = void 0;
4
+ function parseChangelogMarkdown(contents) {
5
+ const CHANGELOG_RELEASE_HEAD_RE = new RegExp('^#{2,}\\s+(\\d+\\.\\d+\\.\\d+)', 'gm');
139
6
  const headings = [...contents.matchAll(CHANGELOG_RELEASE_HEAD_RE)];
140
7
  const releases = [];
141
8
  for (let i = 0; i < headings.length; i++) {
@@ -1,3 +1,7 @@
1
+ /// <reference types="node" />
1
2
  import { Tree } from '../../../generators/tree';
2
3
  export declare function printDiff(before: string, after: string, contextLines?: number, noDiffMessage?: string): void;
3
- export declare function printChanges(tree: Tree, isDryRun: boolean, diffContextLines?: number, shouldPrintDryRunMessage?: boolean, noDiffMessage?: string): void;
4
+ export declare function printChanges(tree: Tree, isDryRun: boolean, diffContextLines?: number, shouldPrintDryRunMessage?: boolean, noDiffMessage?: string, changePredicate?: (f: {
5
+ path: string;
6
+ content?: Buffer;
7
+ }) => boolean): void;
@@ -27,7 +27,8 @@ function printDiff(before, after, contextLines = 1, noDiffMessage = NO_DIFF_MESS
27
27
  console.log('');
28
28
  }
29
29
  exports.printDiff = printDiff;
30
- function printChanges(tree, isDryRun, diffContextLines = 1, shouldPrintDryRunMessage = true, noDiffMessage) {
30
+ function printChanges(tree, isDryRun, diffContextLines = 1, shouldPrintDryRunMessage = true, noDiffMessage, changePredicate) {
31
+ changePredicate = changePredicate || (() => true);
31
32
  const changes = tree.listChanges();
32
33
  console.log('');
33
34
  if (changes.length === 0 && noDiffMessage) {
@@ -35,7 +36,7 @@ function printChanges(tree, isDryRun, diffContextLines = 1, shouldPrintDryRunMes
35
36
  return;
36
37
  }
37
38
  // Print the changes
38
- changes.forEach((f) => {
39
+ changes.filter(changePredicate).forEach((f) => {
39
40
  if (f.type === 'CREATE') {
40
41
  console.error(`${chalk.green('CREATE')} ${f.path}${isDryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
41
42
  printDiff('', f.content?.toString() || '', diffContextLines, noDiffMessage);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.showProjectHandler = exports.showProjectsHandler = void 0;
4
+ const output_1 = require("../../utils/output");
4
5
  const nx_json_1 = require("../../config/nx-json");
5
6
  const affected_project_graph_1 = require("../../project-graph/affected/affected-project-graph");
6
7
  const file_utils_1 = require("../../project-graph/file-utils");
@@ -55,6 +56,7 @@ async function showProjectsHandler(args) {
55
56
  console.log(project);
56
57
  }
57
58
  }
59
+ await output_1.output.drain();
58
60
  process.exit(0);
59
61
  }
60
62
  exports.showProjectsHandler = showProjectsHandler;
@@ -1,3 +1,4 @@
1
+ import type { ChangelogRenderOptions } from '../../changelog-renderer';
1
2
  import { PackageManager } from '../utils/package-manager';
2
3
  import { InputDefinition, TargetConfiguration, TargetDependencyConfig } from './workspace-json-project-json';
3
4
  export type ImplicitDependencyEntry<T = '*' | string[]> = {
@@ -37,6 +38,50 @@ interface NxReleaseVersionConfiguration {
37
38
  generator?: string;
38
39
  generatorOptions?: Record<string, unknown>;
39
40
  }
41
+ /**
42
+ * **ALPHA**
43
+ */
44
+ export interface NxReleaseChangelogConfiguration {
45
+ /**
46
+ * Optionally create a release containing all relevant changes on a supported version control system, it
47
+ * is false by default.
48
+ *
49
+ * NOTE: if createRelease is set on a group of projects, it will cause the default releaseTagPattern of
50
+ * "{projectName}@v{version}" to be used for those projects, even when versioning everything together.
51
+ */
52
+ createRelease?: 'github' | false;
53
+ /**
54
+ * This can either be set to a string value that will be written to the changelog file(s)
55
+ * at the workspace root and/or within project directories, or set to `false` to specify
56
+ * that no changelog entry should be made when there are no code changes.
57
+ *
58
+ * NOTE: The string value has a sensible default value and supports interpolation of
59
+ * {projectName} when generating for project level changelogs.
60
+ *
61
+ * E.g. for a project level changelog you could customize the message to something like:
62
+ * "entryWhenNoChanges": "There were no code changes for {projectName}"
63
+ */
64
+ entryWhenNoChanges?: string | false;
65
+ /**
66
+ * This is either a workspace path where the changelog markdown file will be created and read from,
67
+ * or set to false to disable file creation altogether (e.g. if only using Github releases).
68
+ *
69
+ * Interpolation of {projectName}, {projectRoot} and {workspaceRoot} is supported.
70
+ *
71
+ * The defaults are:
72
+ * - "{workspaceRoot}/CHANGELOG.md" at the workspace level
73
+ * - "{projectRoot}/CHANGELOG.md" at the project level
74
+ */
75
+ file?: string | false;
76
+ /**
77
+ * A path to a valid changelog renderer function used to transform commit messages and other metadata into
78
+ * the final changelog (usually in markdown format). Its output can be modified using the optional `renderOptions`.
79
+ *
80
+ * By default, the renderer is set to "nx/changelog-renderer" which nx provides out of the box.
81
+ */
82
+ renderer?: string;
83
+ renderOptions?: ChangelogRenderOptions;
84
+ }
40
85
  /**
41
86
  * **ALPHA**
42
87
  */
@@ -45,14 +90,46 @@ interface NxReleaseConfiguration {
45
90
  * @note: When no groups are configured at all (the default), all projects in the workspace are treated as
46
91
  * if they were in a release group together.
47
92
  */
48
- groups?: Record<string, {
93
+ groups?: Record<string, // group name
94
+ {
95
+ /**
96
+ * Required list of one or more projects to include in the release group. Any single project can
97
+ * only be used in a maximum of one release group.
98
+ */
49
99
  projects: string[] | string;
50
100
  /**
51
- * If no version config is provided for the group, we will assume that @nx/js:release-version
52
- * is the desired generator implementation, allowing for terser config for the common case.
101
+ * Optionally override version configuration for this group.
53
102
  */
54
103
  version?: NxReleaseVersionConfiguration;
104
+ /**
105
+ * Optionally override project changelog configuration for this group.
106
+ */
107
+ changelog?: NxReleaseChangelogConfiguration | false;
108
+ /**
109
+ * Optionally override the git/release tag pattern to use for this group.
110
+ */
111
+ releaseTagPattern?: string;
55
112
  }>;
113
+ changelog?: {
114
+ workspaceChangelog?: NxReleaseChangelogConfiguration | false;
115
+ projectChangelogs?: NxReleaseChangelogConfiguration | false;
116
+ };
117
+ /**
118
+ * If no version config is provided, we will assume that @nx/js:release-version
119
+ * is the desired generator implementation, allowing for terser config for the common case.
120
+ */
121
+ version?: NxReleaseVersionConfiguration;
122
+ /**
123
+ * Optional override the git/release tag pattern to use. This field is the source of truth
124
+ * for changelog generation and release tagging, as well as for conventional-commits parsing.
125
+ *
126
+ * It supports interpolating the version as {version} and (if releasing independently or forcing
127
+ * project level version control system releases) the project name as {projectName} within the string.
128
+ *
129
+ * The default releaseTagPattern for unified releases is: "v{version}"
130
+ * The default releaseTagPattern for releases at the project level is: "{projectName}@v{version}"
131
+ */
132
+ releaseTagPattern?: string;
56
133
  }
57
134
  /**
58
135
  * Nx.json configuration
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasNxJson = exports.readNxJson = void 0;
4
- const path_1 = require("path");
5
4
  const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
6
  const fileutils_1 = require("../utils/fileutils");
7
7
  const workspace_root_1 = require("../utils/workspace-root");
8
8
  function readNxJson(root = workspace_root_1.workspaceRoot) {
@@ -24,7 +24,7 @@ export interface FileData {
24
24
  */
25
25
  export type FileDataDependency = string | [target: string, type: DependencyType] | [source: string, target: string, type: DependencyType];
26
26
  export declare function fileDataDepTarget(dep: FileDataDependency): string;
27
- export declare function fileDataDepType(dep: FileDataDependency): "static" | DependencyType;
27
+ export declare function fileDataDepType(dep: FileDataDependency): DependencyType | "static";
28
28
  export interface FileMap {
29
29
  nonProjectFiles: FileData[];
30
30
  projectFileMap: ProjectFileMap;
@@ -268,12 +268,6 @@ class DaemonClient {
268
268
  (0, fs_extra_1.ensureFileSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE);
269
269
  this._out = await (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a');
270
270
  this._err = await (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a');
271
- if (this.nxJson.tasksRunnerOptions?.default?.options?.useParcelWatcher) {
272
- DAEMON_ENV_SETTINGS['NX_NATIVE_WATCHER'] = 'false';
273
- }
274
- else {
275
- DAEMON_ENV_SETTINGS['NX_NATIVE_WATCHER'] = 'true';
276
- }
277
271
  const backgroundProcess = (0, child_process_1.spawn)(process.execPath, [(0, path_1.join)(__dirname, '../server/start.js')], {
278
272
  cwd: workspace_root_1.workspaceRoot,
279
273
  stdio: ['ignore', this._out.fd, this._err.fd],
@@ -1,8 +1,8 @@
1
- import type { Event } from '@parcel/watcher';
1
+ import { WatchEvent } from '../../native';
2
2
  export declare function _recordOutputsHash(outputs: string[], hash: string): void;
3
3
  export declare function _outputsHashesMatch(outputs: string[], hash: string): boolean;
4
4
  export declare function recordedHash(output: string): string;
5
5
  export declare function recordOutputsHash(_outputs: string[], hash: string): Promise<void>;
6
6
  export declare function outputsHashesMatch(_outputs: string[], hash: string): Promise<boolean>;
7
- export declare function processFileChangesInOutputs(changeEvents: Event[], now?: number): void;
7
+ export declare function processFileChangesInOutputs(changeEvents: WatchEvent[], now?: number): void;
8
8
  export declare function disableOutputsTracking(): void;
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.disableOutputsTracking = exports.processFileChangesInOutputs = exports.outputsHashesMatch = exports.recordOutputsHash = exports.recordedHash = exports._outputsHashesMatch = exports._recordOutputsHash = void 0;
4
4
  const path_1 = require("path");
5
- const workspace_root_1 = require("../../utils/workspace-root");
6
- const collapse_expanded_outputs_1 = require("../../utils/collapse-expanded-outputs");
7
5
  const native_1 = require("../../native");
6
+ const collapse_expanded_outputs_1 = require("../../utils/collapse-expanded-outputs");
7
+ const workspace_root_1 = require("../../utils/workspace-root");
8
8
  let disabled = false;
9
9
  const dirsContainingOutputs = {};
10
10
  const recordedHashes = {};
@@ -9,7 +9,6 @@ const fileutils_1 = require("../../utils/fileutils");
9
9
  const file_watcher_sockets_1 = require("./file-watching/file-watcher-sockets");
10
10
  const logger_1 = require("./logger");
11
11
  const workspace_root_1 = require("../../utils/workspace-root");
12
- const child_process_1 = require("child_process");
13
12
  const file_hasher_1 = require("../../hasher/file-hasher");
14
13
  const retrieve_workspace_files_1 = require("../../project-graph/utils/retrieve-workspace-files");
15
14
  const nx_json_1 = require("../../config/nx-json");
@@ -91,36 +90,10 @@ function computeWorkspaceConfigHash(projectsConfigurations) {
91
90
  .map(([projectName, projectConfig]) => `${projectName}:${JSON.stringify(projectConfig)}`);
92
91
  return (0, file_hasher_1.hashArray)(projectConfigurationStrings);
93
92
  }
94
- /**
95
- * Temporary work around to handle nested gitignores. The parcel file watcher doesn't handle them well,
96
- * so we need to filter them out here.
97
- *
98
- * TODO(Cammisuli): remove after 16.4 - Rust watcher handles nested gitignores
99
- */
100
- function filterUpdatedFiles(files) {
101
- if (files.length === 0 || process.env.NX_NATIVE_WATCHER === 'true') {
102
- return files;
103
- }
104
- try {
105
- const quoted = files.map((f) => '"' + f + '"');
106
- const ignored = (0, child_process_1.execSync)(`git check-ignore ${quoted.join(' ')}`, {
107
- windowsHide: true,
108
- })
109
- .toString()
110
- .split('\n');
111
- return files.filter((f) => ignored.indexOf(f) === -1);
112
- }
113
- catch (e) {
114
- // none of the files were ignored
115
- return files;
116
- }
117
- }
118
93
  async function processCollectedUpdatedAndDeletedFiles() {
119
94
  try {
120
95
  perf_hooks_1.performance.mark('hash-watched-changes-start');
121
- const updatedFiles = filterUpdatedFiles([
122
- ...collectedUpdatedFiles.values(),
123
- ]);
96
+ const updatedFiles = [...collectedUpdatedFiles.values()];
124
97
  const deletedFiles = [...collectedDeletedFiles.values()];
125
98
  let updatedFileHashes = (0, workspace_context_1.updateFilesInContext)(updatedFiles, deletedFiles);
126
99
  perf_hooks_1.performance.mark('hash-watched-changes-end');