nx 21.0.0-beta.1 → 21.0.0-beta.10

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 (240) hide show
  1. package/.eslintrc.json +5 -1
  2. package/migrations.json +5 -35
  3. package/package.json +12 -12
  4. package/release/index.d.ts +1 -1
  5. package/release/index.js +2 -1
  6. package/schemas/nx-schema.json +182 -35
  7. package/schemas/project-schema.json +5 -0
  8. package/src/adapter/compat.d.ts +1 -1
  9. package/src/adapter/compat.js +3 -0
  10. package/src/command-line/add/add.js +6 -16
  11. package/src/command-line/affected/command-object.js +6 -6
  12. package/src/command-line/examples.js +0 -4
  13. package/src/command-line/exec/command-object.js +1 -1
  14. package/src/command-line/generate/generator-utils.js +8 -3
  15. package/src/command-line/import/import.js +1 -1
  16. package/src/command-line/init/command-object.js +18 -6
  17. package/src/command-line/init/configure-plugins.d.ts +6 -7
  18. package/src/command-line/init/configure-plugins.js +52 -38
  19. package/src/command-line/init/implementation/add-nx-to-turborepo.d.ts +4 -0
  20. package/src/command-line/init/implementation/add-nx-to-turborepo.js +49 -0
  21. package/src/command-line/init/implementation/check-compatible-with-plugins.js +7 -1
  22. package/src/command-line/init/implementation/deduce-default-base.d.ts +1 -0
  23. package/src/command-line/init/implementation/deduce-default-base.js +53 -0
  24. package/src/command-line/init/implementation/react/add-vite-commands-to-package-scripts.js +6 -4
  25. package/src/command-line/init/implementation/react/index.d.ts +1 -1
  26. package/src/command-line/init/implementation/react/index.js +32 -185
  27. package/src/command-line/init/implementation/react/write-vite-config.js +19 -3
  28. package/src/command-line/init/implementation/utils.d.ts +6 -2
  29. package/src/command-line/init/implementation/utils.js +110 -45
  30. package/src/command-line/init/init-v1.js +1 -1
  31. package/src/command-line/init/init-v2.d.ts +1 -0
  32. package/src/command-line/init/init-v2.js +70 -39
  33. package/src/command-line/migrate/migrate-ui-api.d.ts +58 -0
  34. package/src/command-line/migrate/migrate-ui-api.js +227 -0
  35. package/src/command-line/migrate/migrate.d.ts +16 -3
  36. package/src/command-line/migrate/migrate.js +113 -83
  37. package/src/command-line/nx-commands.js +19 -5
  38. package/src/command-line/register/command-object.d.ts +6 -0
  39. package/src/command-line/{activate-powerpack → register}/command-object.js +9 -9
  40. package/src/command-line/register/register.d.ts +2 -0
  41. package/src/command-line/register/register.js +9 -0
  42. package/src/command-line/release/changelog.js +18 -15
  43. package/src/command-line/release/command-object.d.ts +8 -0
  44. package/src/command-line/release/command-object.js +9 -0
  45. package/src/command-line/release/config/config.d.ts +8 -7
  46. package/src/command-line/release/config/config.js +139 -45
  47. package/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
  48. package/src/command-line/release/config/use-legacy-versioning.js +9 -0
  49. package/src/command-line/release/index.d.ts +4 -0
  50. package/src/command-line/release/index.js +6 -1
  51. package/src/command-line/release/plan-check.js +6 -3
  52. package/src/command-line/release/plan.js +7 -3
  53. package/src/command-line/release/publish.js +7 -3
  54. package/src/command-line/release/release.js +8 -3
  55. package/src/command-line/release/utils/batch-projects-by-generator-config.js +6 -3
  56. package/src/command-line/release/utils/git.d.ts +3 -2
  57. package/src/command-line/release/utils/git.js +65 -9
  58. package/src/command-line/release/utils/github.js +3 -1
  59. package/src/command-line/release/utils/resolve-semver-specifier.d.ts +2 -1
  60. package/src/command-line/release/utils/resolve-semver-specifier.js +2 -1
  61. package/src/command-line/release/utils/semver.d.ts +8 -0
  62. package/src/command-line/release/utils/semver.js +8 -0
  63. package/src/command-line/release/utils/shared-legacy.d.ts +25 -0
  64. package/src/command-line/release/utils/shared-legacy.js +2 -0
  65. package/src/command-line/release/utils/shared.d.ts +11 -17
  66. package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts +7 -0
  67. package/src/command-line/release/version/derive-specifier-from-conventional-commits.js +47 -0
  68. package/src/command-line/release/version/deriver-specifier-from-version-plans.d.ts +8 -0
  69. package/src/command-line/release/version/deriver-specifier-from-version-plans.js +59 -0
  70. package/src/command-line/release/version/project-logger.d.ts +8 -0
  71. package/src/command-line/release/version/project-logger.js +45 -0
  72. package/src/command-line/release/version/release-group-processor.d.ts +252 -0
  73. package/src/command-line/release/version/release-group-processor.js +1057 -0
  74. package/src/command-line/release/version/resolve-current-version.d.ts +32 -0
  75. package/src/command-line/release/version/resolve-current-version.js +241 -0
  76. package/src/command-line/release/version/test-utils.d.ts +93 -0
  77. package/src/command-line/release/version/test-utils.js +415 -0
  78. package/src/command-line/release/version/topological-sort.d.ts +9 -0
  79. package/src/command-line/release/version/topological-sort.js +41 -0
  80. package/src/command-line/release/version/version-actions.d.ts +171 -0
  81. package/src/command-line/release/version/version-actions.js +195 -0
  82. package/src/command-line/release/version-legacy.d.ts +46 -0
  83. package/src/command-line/release/version-legacy.js +453 -0
  84. package/src/command-line/release/version.d.ts +0 -40
  85. package/src/command-line/release/version.js +84 -262
  86. package/src/command-line/repair/repair.js +0 -1
  87. package/src/command-line/report/report.d.ts +7 -3
  88. package/src/command-line/report/report.js +52 -18
  89. package/src/command-line/run/command-object.js +2 -2
  90. package/src/command-line/run/executor-utils.d.ts +6 -1
  91. package/src/command-line/run/executor-utils.js +10 -1
  92. package/src/command-line/run/run.js +2 -2
  93. package/src/command-line/run-many/command-object.js +2 -2
  94. package/src/command-line/yargs-utils/shared-options.d.ts +4 -0
  95. package/src/command-line/yargs-utils/shared-options.js +20 -0
  96. package/src/config/misc-interfaces.d.ts +11 -1
  97. package/src/config/nx-json.d.ts +160 -16
  98. package/src/config/project-graph.d.ts +4 -2
  99. package/src/config/project-graph.js +8 -0
  100. package/src/config/workspace-json-project-json.d.ts +2 -2
  101. package/src/core/graph/main.js +1 -1
  102. package/src/core/graph/runtime.js +1 -1
  103. package/src/core/graph/styles.css +2 -2
  104. package/src/core/graph/styles.js +1 -1
  105. package/src/daemon/client/client.d.ts +2 -0
  106. package/src/daemon/client/client.js +15 -0
  107. package/src/daemon/message-types/glob.d.ts +7 -0
  108. package/src/daemon/message-types/glob.js +9 -1
  109. package/src/daemon/message-types/hash-glob.d.ts +6 -0
  110. package/src/daemon/message-types/hash-glob.js +9 -1
  111. package/src/daemon/server/handle-glob.d.ts +1 -0
  112. package/src/daemon/server/handle-glob.js +8 -0
  113. package/src/daemon/server/handle-hash-glob.d.ts +1 -0
  114. package/src/daemon/server/handle-hash-glob.js +8 -0
  115. package/src/daemon/server/logger.js +2 -1
  116. package/src/daemon/server/server.js +7 -0
  117. package/src/devkit-internals.d.ts +3 -2
  118. package/src/devkit-internals.js +5 -1
  119. package/src/executors/run-commands/run-commands.impl.d.ts +2 -5
  120. package/src/executors/run-commands/run-commands.impl.js +14 -42
  121. package/src/executors/run-commands/running-tasks.d.ts +9 -4
  122. package/src/executors/run-commands/running-tasks.js +103 -30
  123. package/src/executors/run-script/run-script.impl.js +4 -3
  124. package/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +8 -0
  125. package/src/generators/testing-utils/create-tree.js +5 -1
  126. package/src/migrations/{update-17-0-0/rm-default-collection-npm-scope.d.ts → update-21-0-0/release-version-config-changes.d.ts} +1 -1
  127. package/src/migrations/update-21-0-0/release-version-config-changes.js +111 -0
  128. package/src/native/index.d.ts +98 -19
  129. package/src/native/index.js +16 -2
  130. package/src/native/native-bindings.js +7 -0
  131. package/src/native/nx.wasi-browser.js +20 -19
  132. package/src/native/nx.wasi.cjs +20 -19
  133. package/src/native/nx.wasm32-wasi.wasm +0 -0
  134. package/src/nx-cloud/nx-cloud-tasks-runner-shell.js +3 -3
  135. package/src/plugins/js/lock-file/lock-file.js +28 -13
  136. package/src/plugins/js/lock-file/utils/package-json.d.ts +1 -1
  137. package/src/plugins/js/lock-file/utils/package-json.js +8 -6
  138. package/src/plugins/js/lock-file/utils/pnpm-normalizer.js +3 -3
  139. package/src/plugins/js/lock-file/yarn-parser.js +85 -39
  140. package/src/plugins/js/project-graph/affected/lock-file-changes.js +1 -0
  141. package/src/plugins/js/project-graph/build-dependencies/explicit-project-dependencies.js +1 -1
  142. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +10 -1
  143. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +59 -6
  144. package/src/plugins/js/utils/packages.js +22 -3
  145. package/src/plugins/js/utils/register.js +1 -0
  146. package/src/plugins/js/utils/typescript.js +3 -3
  147. package/src/plugins/package-json/create-nodes.d.ts +1 -1
  148. package/src/plugins/package-json/create-nodes.js +4 -2
  149. package/src/project-graph/affected/locators/project-glob-changes.js +2 -2
  150. package/src/project-graph/error-types.js +32 -2
  151. package/src/project-graph/file-utils.d.ts +1 -10
  152. package/src/project-graph/file-utils.js +2 -77
  153. package/src/project-graph/plugins/get-plugins.js +2 -1
  154. package/src/project-graph/plugins/in-process-loader.js +1 -1
  155. package/src/project-graph/plugins/isolation/plugin-worker.js +12 -6
  156. package/src/project-graph/plugins/loaded-nx-plugin.d.ts +2 -1
  157. package/src/project-graph/plugins/public-api.d.ts +1 -1
  158. package/src/project-graph/plugins/utils.d.ts +2 -2
  159. package/src/project-graph/plugins/utils.js +2 -2
  160. package/src/project-graph/project-graph.js +1 -1
  161. package/src/project-graph/utils/project-configuration-utils.d.ts +3 -3
  162. package/src/project-graph/utils/project-configuration-utils.js +54 -21
  163. package/src/project-graph/utils/retrieve-workspace-files.d.ts +1 -1
  164. package/src/project-graph/utils/retrieve-workspace-files.js +14 -18
  165. package/src/tasks-runner/batch/batch-messages.d.ts +2 -0
  166. package/src/tasks-runner/batch/run-batch.js +3 -4
  167. package/src/tasks-runner/cache.d.ts +20 -6
  168. package/src/tasks-runner/cache.js +104 -20
  169. package/src/tasks-runner/create-task-graph.d.ts +0 -1
  170. package/src/tasks-runner/create-task-graph.js +11 -11
  171. package/src/tasks-runner/default-tasks-runner.js +5 -14
  172. package/src/tasks-runner/forked-process-task-runner.d.ts +8 -3
  173. package/src/tasks-runner/forked-process-task-runner.js +59 -46
  174. package/src/tasks-runner/init-tasks-runner.d.ts +15 -1
  175. package/src/tasks-runner/init-tasks-runner.js +62 -2
  176. package/src/tasks-runner/is-tui-enabled.d.ts +2 -0
  177. package/src/tasks-runner/is-tui-enabled.js +64 -0
  178. package/src/tasks-runner/life-cycle.d.ts +14 -3
  179. package/src/tasks-runner/life-cycle.js +37 -2
  180. package/src/tasks-runner/life-cycles/task-history-life-cycle-old.d.ts +2 -0
  181. package/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +15 -7
  182. package/src/tasks-runner/life-cycles/task-history-life-cycle.d.ts +5 -0
  183. package/src/tasks-runner/life-cycles/task-history-life-cycle.js +35 -5
  184. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +18 -0
  185. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +229 -0
  186. package/src/tasks-runner/pseudo-terminal.d.ts +10 -7
  187. package/src/tasks-runner/pseudo-terminal.js +37 -35
  188. package/src/tasks-runner/run-command.d.ts +4 -1
  189. package/src/tasks-runner/run-command.js +220 -42
  190. package/src/tasks-runner/running-tasks/node-child-process.js +4 -11
  191. package/src/tasks-runner/running-tasks/running-task.d.ts +3 -0
  192. package/src/tasks-runner/running-tasks/shared-running-task.d.ts +14 -0
  193. package/src/tasks-runner/running-tasks/shared-running-task.js +30 -0
  194. package/src/tasks-runner/task-env.d.ts +1 -4
  195. package/src/tasks-runner/task-env.js +2 -0
  196. package/src/tasks-runner/task-orchestrator.d.ts +26 -10
  197. package/src/tasks-runner/task-orchestrator.js +212 -57
  198. package/src/tasks-runner/tasks-runner.d.ts +1 -0
  199. package/src/tasks-runner/tasks-schedule.d.ts +1 -0
  200. package/src/tasks-runner/tasks-schedule.js +9 -0
  201. package/src/tasks-runner/utils.d.ts +2 -2
  202. package/src/tasks-runner/utils.js +18 -12
  203. package/src/utils/child-process.d.ts +4 -0
  204. package/src/utils/child-process.js +23 -30
  205. package/src/utils/command-line-utils.d.ts +1 -1
  206. package/src/utils/find-matching-projects.js +2 -2
  207. package/src/utils/git-utils.d.ts +1 -1
  208. package/src/utils/git-utils.js +8 -3
  209. package/src/utils/handle-errors.js +15 -0
  210. package/src/utils/is-ci.js +4 -1
  211. package/src/utils/is-using-prettier.d.ts +3 -0
  212. package/src/utils/is-using-prettier.js +62 -0
  213. package/src/utils/nx-key.d.ts +7 -0
  214. package/src/utils/nx-key.js +52 -0
  215. package/src/utils/package-json.d.ts +1 -1
  216. package/src/utils/package-json.js +16 -2
  217. package/src/utils/package-manager.js +2 -2
  218. package/src/utils/path.js +1 -1
  219. package/src/utils/require-nx-key.d.ts +1 -0
  220. package/src/utils/require-nx-key.js +22 -0
  221. package/src/utils/workspace-context.d.ts +2 -0
  222. package/src/utils/workspace-context.js +16 -0
  223. package/src/command-line/activate-powerpack/activate-powerpack.d.ts +0 -2
  224. package/src/command-line/activate-powerpack/activate-powerpack.js +0 -34
  225. package/src/command-line/activate-powerpack/command-object.d.ts +0 -6
  226. package/src/command-line/init/implementation/react/write-craco-config.d.ts +0 -1
  227. package/src/command-line/init/implementation/react/write-craco-config.js +0 -61
  228. package/src/migrations/update-17-0-0/move-cache-directory.d.ts +0 -2
  229. package/src/migrations/update-17-0-0/move-cache-directory.js +0 -35
  230. package/src/migrations/update-17-0-0/rm-default-collection-npm-scope.js +0 -72
  231. package/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.d.ts +0 -2
  232. package/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.js +0 -122
  233. package/src/migrations/update-17-2-0/move-default-base.d.ts +0 -5
  234. package/src/migrations/update-17-2-0/move-default-base.js +0 -21
  235. package/src/migrations/update-17-3-0/nx-release-path.d.ts +0 -3
  236. package/src/migrations/update-17-3-0/nx-release-path.js +0 -47
  237. package/src/migrations/update-18-0-0/disable-crystal-for-existing-workspaces.d.ts +0 -2
  238. package/src/migrations/update-18-0-0/disable-crystal-for-existing-workspaces.js +0 -11
  239. package/src/utils/powerpack.d.ts +0 -5
  240. package/src/utils/powerpack.js +0 -33
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExampleNonSemverVersionActions = exports.ExampleRustVersionActions = void 0;
4
+ exports.createNxReleaseConfigAndPopulateWorkspace = createNxReleaseConfigAndPopulateWorkspace;
5
+ exports.parseGraphDefinition = parseGraphDefinition;
6
+ exports.mockResolveVersionActionsForProjectImplementation = mockResolveVersionActionsForProjectImplementation;
7
+ const j_toml_1 = require("@ltd/j-toml");
8
+ const node_path_1 = require("node:path");
9
+ const json_1 = require("../../../generators/utils/json");
10
+ const file_map_utils_1 = require("../../../project-graph/file-map-utils");
11
+ const config_1 = require("../config/config");
12
+ const filter_release_groups_1 = require("../config/filter-release-groups");
13
+ const version_actions_1 = require("./version-actions");
14
+ async function createNxReleaseConfigAndPopulateWorkspace(tree, graphDefinition, additionalNxReleaseConfig, mockResolveCurrentVersion, filters = {}) {
15
+ const graph = parseGraphDefinition(graphDefinition);
16
+ const { groups, projectGraph } = setupGraph(tree, graph);
17
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), {
18
+ ...additionalNxReleaseConfig,
19
+ groups,
20
+ version: {
21
+ ...additionalNxReleaseConfig.version,
22
+ useLegacyVersioning: false,
23
+ },
24
+ });
25
+ if (configError) {
26
+ throw configError;
27
+ }
28
+ let { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, filters.projects, filters.groups);
29
+ if (filterError) {
30
+ throw filterError;
31
+ }
32
+ // Mock the implementation of resolveCurrentVersion to reliably return the version of the project based on our graph definition
33
+ mockResolveCurrentVersion?.mockImplementation((_, { name }) => {
34
+ for (const [projectName, project] of Object.entries(graph.projects)) {
35
+ if (projectName === name) {
36
+ return project.version ?? null;
37
+ }
38
+ }
39
+ throw new Error(`Unknown project name in test utils: ${name}`);
40
+ });
41
+ return {
42
+ projectGraph,
43
+ nxReleaseConfig: nxReleaseConfig,
44
+ releaseGroups,
45
+ releaseGroupToFilteredProjects,
46
+ filters,
47
+ };
48
+ }
49
+ class ExampleRustVersionActions extends version_actions_1.VersionActions {
50
+ constructor() {
51
+ super(...arguments);
52
+ this.validManifestFilenames = ['Cargo.toml'];
53
+ }
54
+ parseCargoToml(cargoString) {
55
+ return j_toml_1.default.parse(cargoString, {
56
+ x: { comment: true },
57
+ });
58
+ }
59
+ static stringifyCargoToml(cargoToml) {
60
+ const tomlString = j_toml_1.default.stringify(cargoToml, {
61
+ newlineAround: 'section',
62
+ });
63
+ return Array.isArray(tomlString) ? tomlString.join('\n') : tomlString;
64
+ }
65
+ static modifyCargoTable(toml, section, key, value) {
66
+ toml[section] ??= j_toml_1.default.Section({});
67
+ toml[section][key] =
68
+ typeof value === 'object' && !Array.isArray(value)
69
+ ? j_toml_1.default.inline(value)
70
+ : typeof value === 'function'
71
+ ? value()
72
+ : value;
73
+ }
74
+ async readCurrentVersionFromSourceManifest(tree) {
75
+ const cargoTomlPath = (0, node_path_1.join)(this.projectGraphNode.data.root, 'Cargo.toml');
76
+ const cargoTomlString = tree.read(cargoTomlPath, 'utf-8').toString();
77
+ const cargoToml = this.parseCargoToml(cargoTomlString);
78
+ const currentVersion = cargoToml.package?.version || '0.0.0';
79
+ return {
80
+ currentVersion,
81
+ manifestPath: cargoTomlPath,
82
+ };
83
+ }
84
+ async readCurrentVersionFromRegistry(tree, _currentVersionResolverMetadata) {
85
+ // Real registry resolver not needed for this test example
86
+ return {
87
+ currentVersion: (await this.readCurrentVersionFromSourceManifest(tree))
88
+ .currentVersion,
89
+ logText: 'https://example.com/fake-registry',
90
+ };
91
+ }
92
+ async updateProjectVersion(tree, newVersion) {
93
+ const logMessages = [];
94
+ for (const manifestToUpdate of this.manifestsToUpdate) {
95
+ const cargoTomlString = tree
96
+ .read(manifestToUpdate.manifestPath, 'utf-8')
97
+ .toString();
98
+ const cargoToml = this.parseCargoToml(cargoTomlString);
99
+ ExampleRustVersionActions.modifyCargoTable(cargoToml, 'package', 'version', newVersion);
100
+ const updatedCargoTomlString = ExampleRustVersionActions.stringifyCargoToml(cargoToml);
101
+ tree.write(manifestToUpdate.manifestPath, updatedCargoTomlString);
102
+ logMessages.push(`✍️ New version ${newVersion} written to manifest: ${manifestToUpdate.manifestPath}`);
103
+ }
104
+ return logMessages;
105
+ }
106
+ async readCurrentVersionOfDependency(tree, _projectGraph, dependencyProjectName) {
107
+ const cargoTomlPath = (0, node_path_1.join)(this.projectGraphNode.data.root, 'Cargo.toml');
108
+ const cargoTomlString = tree.read(cargoTomlPath, 'utf-8').toString();
109
+ const cargoToml = this.parseCargoToml(cargoTomlString);
110
+ const dependencyVersion = cargoToml.dependencies?.[dependencyProjectName];
111
+ if (typeof dependencyVersion === 'string') {
112
+ return {
113
+ currentVersion: dependencyVersion,
114
+ dependencyCollection: 'dependencies',
115
+ };
116
+ }
117
+ return {
118
+ currentVersion: dependencyVersion?.version || '0.0.0',
119
+ dependencyCollection: 'dependencies',
120
+ };
121
+ }
122
+ // NOTE: Does not take the preserveLocalDependencyProtocols setting into account yet
123
+ async updateProjectDependencies(tree, _projectGraph, dependenciesToUpdate) {
124
+ const numDependenciesToUpdate = Object.keys(dependenciesToUpdate).length;
125
+ const depText = numDependenciesToUpdate === 1 ? 'dependency' : 'dependencies';
126
+ if (numDependenciesToUpdate === 0) {
127
+ return [];
128
+ }
129
+ const logMessages = [];
130
+ for (const manifestToUpdate of this.manifestsToUpdate) {
131
+ const cargoTomlString = tree
132
+ .read(manifestToUpdate.manifestPath, 'utf-8')
133
+ .toString();
134
+ const cargoToml = this.parseCargoToml(cargoTomlString);
135
+ for (const [dep, version] of Object.entries(dependenciesToUpdate)) {
136
+ ExampleRustVersionActions.modifyCargoTable(cargoToml, 'dependencies', dep, version);
137
+ }
138
+ const updatedCargoTomlString = ExampleRustVersionActions.stringifyCargoToml(cargoToml);
139
+ tree.write(manifestToUpdate.manifestPath, updatedCargoTomlString);
140
+ logMessages.push(`✍️ Updated ${numDependenciesToUpdate} ${depText} in manifest: ${manifestToUpdate.manifestPath}`);
141
+ }
142
+ return logMessages;
143
+ }
144
+ }
145
+ exports.ExampleRustVersionActions = ExampleRustVersionActions;
146
+ class ExampleNonSemverVersionActions extends version_actions_1.VersionActions {
147
+ constructor() {
148
+ super(...arguments);
149
+ this.validManifestFilenames = null;
150
+ }
151
+ async readCurrentVersionFromSourceManifest() {
152
+ return null;
153
+ }
154
+ async readCurrentVersionFromRegistry() {
155
+ return null;
156
+ }
157
+ async readCurrentVersionOfDependency() {
158
+ return {
159
+ currentVersion: null,
160
+ dependencyCollection: null,
161
+ };
162
+ }
163
+ async updateProjectVersion(tree, newVersion) {
164
+ tree.write((0, node_path_1.join)(this.projectGraphNode.data.root, 'version.txt'), newVersion);
165
+ return [];
166
+ }
167
+ async updateProjectDependencies() {
168
+ return [];
169
+ }
170
+ // Overwrite the default calculateNewVersion method to return the new version directly and not consider semver
171
+ async calculateNewVersion(currentVersion, newVersionInput, newVersionInputReason, newVersionInputReasonData, preid) {
172
+ if (newVersionInput === 'patch') {
173
+ return {
174
+ newVersion: '{SOME_NEW_VERSION_DERIVED_AS_A_SIDE_EFFECT_OF_DEPENDENCY_BUMP}',
175
+ logText: `Determined new version as a side effect of dependency bump: ${newVersionInput}`,
176
+ };
177
+ }
178
+ return {
179
+ newVersion: newVersionInput,
180
+ logText: `Applied new version directly: ${newVersionInput}`,
181
+ };
182
+ }
183
+ }
184
+ exports.ExampleNonSemverVersionActions = ExampleNonSemverVersionActions;
185
+ function parseGraphDefinition(definition) {
186
+ const graph = { projects: {} };
187
+ const lines = definition.trim().split('\n');
188
+ let currentGroup = '';
189
+ let groupConfig = {};
190
+ let groupRelationship = '';
191
+ let lastProjectName = '';
192
+ lines.forEach((line) => {
193
+ line = line.trim();
194
+ if (!line) {
195
+ // Skip empty lines
196
+ return;
197
+ }
198
+ // Match group definitions with JSON config
199
+ const groupMatch = line.match(/^(\w+)\s*\(\s*(\{.*?\})\s*\):$/);
200
+ if (groupMatch) {
201
+ currentGroup = groupMatch[1];
202
+ groupConfig = JSON.parse(groupMatch[2]);
203
+ groupRelationship = groupConfig['projectsRelationship'] || 'independent';
204
+ return;
205
+ }
206
+ // Match project definitions with optional per-project JSON config
207
+ const projectMatch = line.match(/^- ([\w-]+)(?:\[([\w\/-]+)\])?(?:@([\w\.-]+))? \[([\w-]+)(?::([^[\]]+))?\](?:\s*\(\s*(\{.*?\})\s*\))?$/);
208
+ if (projectMatch) {
209
+ const [_, name, customProjectRoot, version, language, alternateNameInManifest, configJson,] = projectMatch;
210
+ // Automatically add data for Rust projects
211
+ let projectData = {};
212
+ if (customProjectRoot) {
213
+ projectData.root = customProjectRoot;
214
+ }
215
+ if (language === 'rust') {
216
+ projectData = {
217
+ release: { versionActions: exampleRustVersionActions },
218
+ };
219
+ }
220
+ else if (language === 'non-semver') {
221
+ projectData = {
222
+ release: { versionActions: exampleNonSemverVersionActions },
223
+ };
224
+ }
225
+ // Merge explicit per-project config if present
226
+ if (configJson) {
227
+ const explicitConfig = JSON.parse(configJson);
228
+ projectData = { ...projectData, ...explicitConfig };
229
+ }
230
+ graph.projects[name] = {
231
+ version: version ?? null,
232
+ language,
233
+ group: currentGroup,
234
+ relationship: groupRelationship,
235
+ dependsOn: [],
236
+ data: projectData,
237
+ // E.g. package name in package.json doesn't necessarily match the name of the nx project
238
+ alternateNameInManifest,
239
+ };
240
+ lastProjectName = name;
241
+ return;
242
+ }
243
+ // Match release config overrides
244
+ const releaseConfigMatch = line.match(/^-> release config overrides (\{.*\})$/);
245
+ if (releaseConfigMatch) {
246
+ const [_, releaseConfigJson] = releaseConfigMatch;
247
+ const releaseConfigOverrides = JSON.parse(releaseConfigJson);
248
+ if (!graph.projects[lastProjectName].releaseConfigOverrides) {
249
+ graph.projects[lastProjectName].releaseConfigOverrides = {};
250
+ }
251
+ graph.projects[lastProjectName].releaseConfigOverrides = {
252
+ ...graph.projects[lastProjectName].releaseConfigOverrides,
253
+ ...releaseConfigOverrides,
254
+ };
255
+ return;
256
+ }
257
+ // Match dependencies
258
+ const dependsMatch = line.match(/^-> depends on ([~^=]?)([\w-]+)(?:\((.*?)\))?(?:\s*\{(\w+)\})?$/);
259
+ if (dependsMatch) {
260
+ const [_, prefix, depProject, versionSpecifier, depCollection = 'dependencies',] = dependsMatch;
261
+ // Add the dependency to the last added project
262
+ if (!graph.projects[lastProjectName].dependsOn) {
263
+ graph.projects[lastProjectName].dependsOn = [];
264
+ }
265
+ graph.projects[lastProjectName].dependsOn.push({
266
+ project: depProject,
267
+ collection: depCollection,
268
+ prefix: prefix || '', // Store the prefix (empty string if not specified)
269
+ versionSpecifier: versionSpecifier || undefined, // Store exact version specifier if provided
270
+ });
271
+ return;
272
+ }
273
+ // Ignore unrecognized lines
274
+ });
275
+ return graph;
276
+ }
277
+ function setupGraph(tree, graph) {
278
+ const groups = {};
279
+ const projectGraph = { nodes: {}, dependencies: {} };
280
+ for (const [projectName, projectData] of Object.entries(graph.projects)) {
281
+ const { version, language, group, relationship, dependsOn, data, alternateNameInManifest, releaseConfigOverrides, } = projectData;
282
+ const packageName = alternateNameInManifest ?? projectName;
283
+ // Write project files based on language
284
+ if (language === 'js') {
285
+ const packageJson = {
286
+ name: packageName,
287
+ version,
288
+ };
289
+ if (dependsOn) {
290
+ dependsOn.forEach((dep) => {
291
+ if (!packageJson[dep.collection]) {
292
+ packageJson[dep.collection] = {};
293
+ }
294
+ const depNode = graph.projects[dep.project];
295
+ const depVersion = dep.versionSpecifier ?? depNode.version;
296
+ packageJson[dep.collection][depNode.alternateNameInManifest ?? dep.project] = `${dep.prefix}${depVersion}`;
297
+ });
298
+ }
299
+ (0, json_1.writeJson)(tree, (0, node_path_1.join)(data.root ?? projectName, 'package.json'), packageJson);
300
+ // Write extra manifest files if specified
301
+ if (releaseConfigOverrides?.version?.manifestRootsToUpdate) {
302
+ releaseConfigOverrides.version.manifestRootsToUpdate.forEach((root) => {
303
+ (0, json_1.writeJson)(tree, (0, node_path_1.join)(root, 'package.json'), packageJson);
304
+ });
305
+ }
306
+ }
307
+ else if (language === 'rust') {
308
+ const cargoToml = {};
309
+ ExampleRustVersionActions.modifyCargoTable(cargoToml, 'package', 'name', projectName);
310
+ ExampleRustVersionActions.modifyCargoTable(cargoToml, 'package', 'version', version);
311
+ if (dependsOn) {
312
+ dependsOn.forEach((dep) => {
313
+ ExampleRustVersionActions.modifyCargoTable(cargoToml, dep.collection, dep.project, {
314
+ version: dep.versionSpecifier ?? graph.projects[dep.project].version,
315
+ });
316
+ });
317
+ }
318
+ const contents = ExampleRustVersionActions.stringifyCargoToml(cargoToml);
319
+ tree.write((0, node_path_1.join)(data.root ?? projectName, 'Cargo.toml'), contents);
320
+ // Write extra manifest files if specified
321
+ if (releaseConfigOverrides?.version?.manifestRootsToUpdate) {
322
+ releaseConfigOverrides.version.manifestRootsToUpdate.forEach((root) => {
323
+ tree.write((0, node_path_1.join)(root, 'Cargo.toml'), contents);
324
+ });
325
+ }
326
+ }
327
+ else if (language === 'non-semver') {
328
+ tree.write((0, node_path_1.join)(data.root ?? projectName, 'version.txt'), version ?? '');
329
+ }
330
+ // Add to projectGraph nodes
331
+ const projectGraphProjectNode = {
332
+ name: projectName,
333
+ type: 'lib',
334
+ data: {
335
+ root: projectName,
336
+ ...data, // Merge any additional data from project config
337
+ },
338
+ };
339
+ if (language === 'js') {
340
+ // Always add the js package metadata to match the @nx/js plugin
341
+ projectGraphProjectNode.data.metadata = {
342
+ js: {
343
+ packageName,
344
+ },
345
+ };
346
+ }
347
+ // Add project level release config overrides
348
+ if (releaseConfigOverrides) {
349
+ projectGraphProjectNode.data.release = {
350
+ ...projectGraphProjectNode.data.release,
351
+ ...releaseConfigOverrides,
352
+ };
353
+ }
354
+ projectGraph.nodes[projectName] = projectGraphProjectNode;
355
+ // Initialize dependencies
356
+ projectGraph.dependencies[projectName] = [];
357
+ // Handle dependencies
358
+ if (dependsOn) {
359
+ dependsOn.forEach((dep) => {
360
+ projectGraph.dependencies[projectName].push({
361
+ source: projectName,
362
+ target: dep.project,
363
+ type: 'static',
364
+ });
365
+ });
366
+ }
367
+ // Add to releaseGroups
368
+ if (!groups[group]) {
369
+ groups[group] = {
370
+ projectsRelationship: relationship,
371
+ projects: [],
372
+ };
373
+ }
374
+ groups[group].projects.push(projectName);
375
+ }
376
+ return { groups, projectGraph };
377
+ }
378
+ const exampleRustVersionActions = '__EXAMPLE_RUST_VERSION_ACTIONS__';
379
+ const exampleNonSemverVersionActions = '__EXAMPLE_NON_SEMVER_VERSION_ACTIONS__';
380
+ async function mockResolveVersionActionsForProjectImplementation(tree, releaseGroup, projectGraphNode, finalConfigForProject) {
381
+ if (projectGraphNode.data.release?.versionActions ===
382
+ exampleRustVersionActions ||
383
+ releaseGroup.versionActions === exampleRustVersionActions) {
384
+ const versionActions = new ExampleRustVersionActions(releaseGroup, projectGraphNode, finalConfigForProject);
385
+ // Initialize the versionActions with all the required manifest paths etc
386
+ await versionActions.init(tree);
387
+ return {
388
+ versionActionsPath: exampleRustVersionActions,
389
+ versionActions,
390
+ };
391
+ }
392
+ if (projectGraphNode.data.release?.versionActions ===
393
+ exampleNonSemverVersionActions ||
394
+ releaseGroup.versionActions === exampleNonSemverVersionActions) {
395
+ const versionActions = new ExampleNonSemverVersionActions(releaseGroup, projectGraphNode, finalConfigForProject);
396
+ // Initialize the versionActions with all the required manifest paths etc
397
+ await versionActions.init(tree);
398
+ return {
399
+ versionActionsPath: exampleNonSemverVersionActions,
400
+ versionActions,
401
+ };
402
+ }
403
+ const versionActionsPath = config_1.DEFAULT_VERSION_ACTIONS_PATH;
404
+ // @ts-ignore
405
+ const loaded = jest.requireActual(versionActionsPath);
406
+ const JsVersionActions = loaded.default;
407
+ const versionActions = new JsVersionActions(releaseGroup, projectGraphNode, finalConfigForProject);
408
+ // Initialize the versionActions with all the required manifest paths etc
409
+ await versionActions.init(tree);
410
+ return {
411
+ versionActionsPath,
412
+ versionActions: versionActions,
413
+ afterAllProjectsVersioned: loaded.afterAllProjectsVersioned,
414
+ };
415
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Topologically sorts a directed graph, returning the sorted nodes.
3
+ * Handles cycles by breaking them where needed.
4
+ *
5
+ * @param nodes All nodes in the graph
6
+ * @param getEdges Function that returns outgoing edges for a node
7
+ * @returns Topologically sorted list of nodes
8
+ */
9
+ export declare function topologicalSort<T>(nodes: T[], getEdges: (node: T) => T[]): T[];
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.topologicalSort = topologicalSort;
4
+ /**
5
+ * Topologically sorts a directed graph, returning the sorted nodes.
6
+ * Handles cycles by breaking them where needed.
7
+ *
8
+ * @param nodes All nodes in the graph
9
+ * @param getEdges Function that returns outgoing edges for a node
10
+ * @returns Topologically sorted list of nodes
11
+ */
12
+ function topologicalSort(nodes, getEdges) {
13
+ const result = [];
14
+ const visited = new Set();
15
+ const temp = new Set();
16
+ function visit(node) {
17
+ // Node is already in result
18
+ if (visited.has(node)) {
19
+ return;
20
+ }
21
+ // Cycle detected, skip this edge to break the cycle
22
+ if (temp.has(node)) {
23
+ return;
24
+ }
25
+ temp.add(node);
26
+ // Visit all dependencies first
27
+ for (const dep of getEdges(node)) {
28
+ visit(dep);
29
+ }
30
+ temp.delete(node);
31
+ visited.add(node);
32
+ result.push(node);
33
+ }
34
+ // Visit all nodes
35
+ for (const node of nodes) {
36
+ if (!visited.has(node)) {
37
+ visit(node);
38
+ }
39
+ }
40
+ return result.reverse();
41
+ }
@@ -0,0 +1,171 @@
1
+ import { ReleaseType } from 'semver';
2
+ import { NxReleaseVersionConfiguration } from '../../../config/nx-json';
3
+ import type { ProjectGraph, ProjectGraphDependency, ProjectGraphProjectNode } from '../../../config/project-graph';
4
+ import type { Tree } from '../../../generators/tree';
5
+ import { ReleaseGroupWithName } from '../config/filter-release-groups';
6
+ import { FinalConfigForProject } from './release-group-processor';
7
+ export type SemverBumpType = ReleaseType | 'none';
8
+ /**
9
+ * Implementation details of performing any actions after all projects have been versioned.
10
+ * An example might be updating a workspace level lock file.
11
+ *
12
+ * NOTE: By the time this function is invoked, the tree will have been flushed back to disk,
13
+ * so it is not accessible here.
14
+ *
15
+ * The function should return lists of changed and deleted files so that they can be staged
16
+ * and committed if appropriate.
17
+ *
18
+ * NOTE: The versionActionsOptions passed here are the ones at the root of release.version config,
19
+ * different values per release group or project will not be respected here because this takes
20
+ * place after all projects have been versioned.
21
+ */
22
+ export type AfterAllProjectsVersioned = (cwd: string, opts: {
23
+ dryRun?: boolean;
24
+ verbose?: boolean;
25
+ rootVersionActionsOptions?: Record<string, unknown>;
26
+ }) => Promise<{
27
+ changedFiles: string[];
28
+ deletedFiles: string[];
29
+ }>;
30
+ export declare function resolveVersionActionsForProject(tree: Tree, releaseGroup: ReleaseGroupWithName, projectGraphNode: ProjectGraphProjectNode, finalConfigForProject: FinalConfigForProject): Promise<{
31
+ versionActionsPath: string;
32
+ versionActions: VersionActions;
33
+ afterAllProjectsVersioned: AfterAllProjectsVersioned;
34
+ }>;
35
+ export declare abstract class VersionActions {
36
+ releaseGroup: ReleaseGroupWithName;
37
+ projectGraphNode: ProjectGraphProjectNode;
38
+ finalConfigForProject: FinalConfigForProject;
39
+ /**
40
+ * The available valid filenames of the manifest file relevant to the current versioning use-case.
41
+ *
42
+ * E.g. for JavaScript projects this would be ["package.json"], but for Gradle it would be
43
+ * ["build.gradle", "build.gradle.kts"].
44
+ *
45
+ * If a manifest file is not applicable to the current versioning use-case, this should be set to null.
46
+ */
47
+ abstract validManifestFilenames: string[] | null;
48
+ /**
49
+ * The interpolated manifest paths to update, if applicable based on the user's configuration, when new
50
+ * versions and dependencies are determined. If no manifest files should be updated based on the user's
51
+ * configuration, this will be an empty array.
52
+ *
53
+ * The final value for preserveLocalDependencyProtocols will be based on the resolved config for the current
54
+ * project and any overrides from the user's configuration for the manifestRootsToUpdate.
55
+ */
56
+ manifestsToUpdate: {
57
+ manifestPath: string;
58
+ preserveLocalDependencyProtocols: boolean;
59
+ }[];
60
+ constructor(releaseGroup: ReleaseGroupWithName, projectGraphNode: ProjectGraphProjectNode, finalConfigForProject: FinalConfigForProject);
61
+ /**
62
+ * Asynchronous initialization of the version actions and validation of certain configuration options.
63
+ */
64
+ init(tree: Tree): Promise<void>;
65
+ /**
66
+ * The default implementation will calculate the new version based on semver. If semver is not applicable to a
67
+ * particular versioning use-case, this method should be overridden with custom logic.
68
+ *
69
+ * @param {string | null} currentVersion - The current version of the project, or null if the current version resolver is set to 'none'
70
+ * @param {string} newVersionInput - The new version input provided by the user, such as a semver relative bump type, or an explicit version
71
+ * @param {string} newVersionInputReason - The reason for the new version input used to inform the log message to show to the user
72
+ * @param {Record<string, unknown>} newVersionInputReasonData - The data to interpolate into the new version input reason
73
+ * @param {string} preid - The preid to use for the new version, if applicable
74
+ */
75
+ calculateNewVersion(currentVersion: string | null, newVersionInput: string, newVersionInputReason: string, newVersionInputReasonData: Record<string, unknown>, preid: string): Promise<{
76
+ newVersion: string;
77
+ logText: string;
78
+ }>;
79
+ /**
80
+ * Implementation details of resolving a project's current version from a valid manifest file. It should
81
+ * return an object with the current version and the filename of the resolved manifest path so that the
82
+ * logs provided to the user are as specific as possible.
83
+ *
84
+ * This method will only be called if the user has configured their currentVersionResolver to be "disk".
85
+ *
86
+ * If the version actions implementation does not support a manifest file, this method can either throw
87
+ * an error or return null. In this case, nx release will handle showing the user a relevant error about
88
+ * their currentVersionResolver configuration being fundamentally incompatible with the current version
89
+ * actions implementation resolved for the project being versioned and they can change it to something else
90
+ * (e.g. "registry" or "git-tag").
91
+ *
92
+ * NOTE: The version actions implementation does not need to provide the method for handling resolution
93
+ * from git tags, this is done directly by nx release.
94
+ */
95
+ abstract readCurrentVersionFromSourceManifest(tree: Tree): Promise<{
96
+ currentVersion: string;
97
+ manifestPath: string;
98
+ } | null>;
99
+ /**
100
+ * Implementation details of resolving a project's current version from a remote registry.
101
+ *
102
+ * The specific logText it returns will be combined with the generic remote registry log text and allows
103
+ * the implementation to provide more specific information to the user about what registry URL
104
+ * was used, what dist-tag etc.
105
+ *
106
+ * If the version actions implementation does not support resolving from a remote registry, this method
107
+ * can either throw an error or return null. In this case, nx release will handle showing the user a relevant
108
+ * error about their currentVersionResolver configuration being fundamentally incompatible with the current
109
+ * version actions implementation resolved for the project being versioned and they can change it to something
110
+ * else (e.g. "disk" or "git-tag").
111
+ *
112
+ * NOTE: The version actions implementation does not need to provide the method for handling resolution
113
+ * from git tags, this is done directly by nx release.
114
+ */
115
+ abstract readCurrentVersionFromRegistry(tree: Tree, currentVersionResolverMetadata: NxReleaseVersionConfiguration['currentVersionResolverMetadata']): Promise<{
116
+ currentVersion: string | null;
117
+ logText: string;
118
+ } | null>;
119
+ /**
120
+ * Implementation details of resolving the dependencies of a project.
121
+ *
122
+ * The default implementation will read dependencies from the Nx project graph. In many cases this will be sufficient,
123
+ * because the project graph will have been constructed using plugins from relevant ecosystems that should have applied
124
+ * any and all relevant metadata to the project nodes and dependency edges.
125
+ *
126
+ * If, however, the project graph cannot be used as the source of truth for whatever reason, then this default method
127
+ * can simply be overridden in the final version actions implementation.
128
+ */
129
+ readDependencies(tree: Tree, projectGraph: ProjectGraph): Promise<ProjectGraphDependency[]>;
130
+ /**
131
+ * Implementation details of resolving the current version of a specific dependency of the project.
132
+ *
133
+ * The dependency collection is the type of dependency collection to which the dependency belongs, such as 'dependencies',
134
+ * 'devDependencies', 'peerDependencies', 'optionalDependencies', etc. This is ecosystem and use-case specific.
135
+ *
136
+ * The currentVersion and dependencyCollection fields will be used to populate the rawVersionSpec and dependencyCollection
137
+ * fields on the VersionData that gets returned from the programmatic API. `null` values are accepted for these if the current
138
+ * version or dependencyCollection is not applicable/resolvable at all, but they should be provided if possible.
139
+ *
140
+ * The currentVersion will also be used when calculating the final versionPrefix to apply for the new dependency
141
+ * version, based on the user's configuration, if applicable.
142
+ */
143
+ abstract readCurrentVersionOfDependency(tree: Tree, projectGraph: ProjectGraph, dependencyProjectName: string): Promise<{
144
+ currentVersion: string | null;
145
+ dependencyCollection: string | null;
146
+ }>;
147
+ /**
148
+ * Implementation details of updating a newly derived version in some source of truth.
149
+ *
150
+ * For libraries/packages, this will usually involve writing to one or more manifest files
151
+ * (e.g. potentially both src and dist), such as a package.json/Cargo.toml/etc, but for
152
+ * application deployments it might involve updating something else instead, it depends on
153
+ * the type of application.
154
+ *
155
+ * It should return an array of log messages that will be displayed unmodified to the user
156
+ * after the version has been updated.
157
+ */
158
+ abstract updateProjectVersion(tree: Tree, newVersion: string): Promise<string[]>;
159
+ /**
160
+ * Implementation details of updating dependencies in some source of truth.
161
+ *
162
+ * For libraries/packages, this will usually involve writing to one or more manifest files
163
+ * (e.g. potentially both src and dist), such as a package.json/Cargo.toml/etc,
164
+ * with new dependency versions, but for application deployments it might involve
165
+ * updating something else instead, it depends on the type of application.
166
+ *
167
+ * It should return an array of log messages that will be displayed unmodified to the user
168
+ * after the dependencies have been updated.
169
+ */
170
+ abstract updateProjectDependencies(tree: Tree, projectGraph: ProjectGraph, dependenciesToUpdate: Record<string, string>): Promise<string[]>;
171
+ }