nx 21.0.0-beta.0 → 21.0.0-beta.2
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.
- package/.eslintrc.json +5 -1
- package/package.json +12 -12
- package/release/index.d.ts +1 -1
- package/release/index.js +2 -1
- package/schemas/nx-schema.json +186 -35
- package/src/adapter/compat.d.ts +1 -1
- package/src/adapter/compat.js +3 -0
- package/src/command-line/add/add.js +6 -16
- package/src/command-line/affected/command-object.js +6 -6
- package/src/command-line/examples.js +0 -4
- package/src/command-line/exec/command-object.js +1 -1
- package/src/command-line/generate/generator-utils.js +8 -3
- package/src/command-line/import/import.js +1 -1
- package/src/command-line/init/command-object.js +18 -6
- package/src/command-line/init/configure-plugins.d.ts +6 -7
- package/src/command-line/init/configure-plugins.js +47 -35
- package/src/command-line/init/implementation/add-nx-to-turborepo.d.ts +4 -0
- package/src/command-line/init/implementation/add-nx-to-turborepo.js +49 -0
- package/src/command-line/init/implementation/check-compatible-with-plugins.js +7 -1
- package/src/command-line/init/implementation/deduce-default-base.d.ts +1 -0
- package/src/command-line/init/implementation/deduce-default-base.js +53 -0
- package/src/command-line/init/implementation/react/add-vite-commands-to-package-scripts.js +6 -4
- package/src/command-line/init/implementation/react/index.d.ts +1 -1
- package/src/command-line/init/implementation/react/index.js +32 -185
- package/src/command-line/init/implementation/react/write-vite-config.js +19 -3
- package/src/command-line/init/implementation/utils.d.ts +4 -1
- package/src/command-line/init/implementation/utils.js +108 -44
- package/src/command-line/init/init-v1.js +1 -1
- package/src/command-line/init/init-v2.d.ts +1 -0
- package/src/command-line/init/init-v2.js +68 -38
- package/src/command-line/migrate/migrate.js +21 -18
- package/src/command-line/nx-commands.js +19 -5
- package/src/command-line/register/command-object.d.ts +6 -0
- package/src/command-line/{activate-powerpack → register}/command-object.js +9 -9
- package/src/command-line/register/register.d.ts +2 -0
- package/src/command-line/register/register.js +9 -0
- package/src/command-line/release/changelog.js +18 -15
- package/src/command-line/release/command-object.d.ts +2 -0
- package/src/command-line/release/command-object.js +9 -0
- package/src/command-line/release/config/config.d.ts +8 -7
- package/src/command-line/release/config/config.js +129 -42
- package/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
- package/src/command-line/release/config/use-legacy-versioning.js +9 -0
- package/src/command-line/release/index.d.ts +4 -0
- package/src/command-line/release/index.js +6 -1
- package/src/command-line/release/plan-check.js +6 -3
- package/src/command-line/release/plan.js +7 -3
- package/src/command-line/release/publish.js +7 -3
- package/src/command-line/release/release.js +8 -3
- package/src/command-line/release/utils/batch-projects-by-generator-config.js +6 -3
- package/src/command-line/release/utils/git.d.ts +3 -2
- package/src/command-line/release/utils/git.js +65 -9
- package/src/command-line/release/utils/github.js +3 -1
- package/src/command-line/release/utils/resolve-semver-specifier.d.ts +2 -1
- package/src/command-line/release/utils/resolve-semver-specifier.js +2 -1
- package/src/command-line/release/utils/semver.d.ts +8 -0
- package/src/command-line/release/utils/semver.js +8 -0
- package/src/command-line/release/utils/shared-legacy.d.ts +25 -0
- package/src/command-line/release/utils/shared-legacy.js +2 -0
- package/src/command-line/release/utils/shared.d.ts +11 -17
- package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts +7 -0
- package/src/command-line/release/version/derive-specifier-from-conventional-commits.js +47 -0
- package/src/command-line/release/version/deriver-specifier-from-version-plans.d.ts +8 -0
- package/src/command-line/release/version/deriver-specifier-from-version-plans.js +59 -0
- package/src/command-line/release/version/project-logger.d.ts +8 -0
- package/src/command-line/release/version/project-logger.js +45 -0
- package/src/command-line/release/version/release-group-processor.d.ts +251 -0
- package/src/command-line/release/version/release-group-processor.js +1040 -0
- package/src/command-line/release/version/resolve-current-version.d.ts +32 -0
- package/src/command-line/release/version/resolve-current-version.js +241 -0
- package/src/command-line/release/version/test-utils.d.ts +95 -0
- package/src/command-line/release/version/test-utils.js +416 -0
- package/src/command-line/release/version/topological-sort.d.ts +9 -0
- package/src/command-line/release/version/topological-sort.js +41 -0
- package/src/command-line/release/version/version-actions.d.ts +170 -0
- package/src/command-line/release/version/version-actions.js +183 -0
- package/src/command-line/release/version-legacy.d.ts +46 -0
- package/src/command-line/release/version-legacy.js +453 -0
- package/src/command-line/release/version.d.ts +0 -40
- package/src/command-line/release/version.js +80 -262
- package/src/command-line/report/report.d.ts +7 -3
- package/src/command-line/report/report.js +52 -18
- package/src/command-line/run/command-object.js +2 -2
- package/src/command-line/run/run.js +1 -1
- package/src/command-line/run-many/command-object.js +2 -2
- package/src/command-line/yargs-utils/shared-options.d.ts +4 -0
- package/src/command-line/yargs-utils/shared-options.js +20 -0
- package/src/config/nx-json.d.ts +153 -15
- package/src/config/project-graph.d.ts +4 -2
- package/src/config/project-graph.js +8 -0
- package/src/config/workspace-json-project-json.d.ts +2 -2
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/runtime.js +1 -1
- package/src/core/graph/styles.css +2 -2
- package/src/core/graph/styles.js +1 -1
- package/src/daemon/client/client.d.ts +2 -0
- package/src/daemon/client/client.js +15 -0
- package/src/daemon/message-types/glob.d.ts +7 -0
- package/src/daemon/message-types/glob.js +9 -1
- package/src/daemon/message-types/hash-glob.d.ts +6 -0
- package/src/daemon/message-types/hash-glob.js +9 -1
- package/src/daemon/server/handle-glob.d.ts +1 -0
- package/src/daemon/server/handle-glob.js +8 -0
- package/src/daemon/server/handle-hash-glob.d.ts +1 -0
- package/src/daemon/server/handle-hash-glob.js +8 -0
- package/src/daemon/server/logger.js +2 -1
- package/src/daemon/server/server.js +7 -0
- package/src/devkit-internals.d.ts +2 -1
- package/src/devkit-internals.js +4 -1
- package/src/executors/run-commands/run-commands.impl.d.ts +3 -5
- package/src/executors/run-commands/run-commands.impl.js +14 -42
- package/src/executors/run-commands/running-tasks.d.ts +7 -5
- package/src/executors/run-commands/running-tasks.js +64 -27
- package/src/executors/run-script/run-script.impl.js +3 -3
- package/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +8 -0
- package/src/generators/testing-utils/create-tree.js +5 -1
- package/src/native/index.d.ts +93 -19
- package/src/native/native-bindings.js +6 -0
- package/src/native/nx.wasi-browser.js +20 -19
- package/src/native/nx.wasi.cjs +20 -19
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/nx-cloud-tasks-runner-shell.js +3 -3
- package/src/plugins/js/lock-file/lock-file.js +28 -13
- package/src/plugins/js/lock-file/utils/package-json.d.ts +1 -1
- package/src/plugins/js/lock-file/utils/package-json.js +2 -1
- package/src/plugins/js/lock-file/yarn-parser.js +85 -39
- package/src/plugins/js/project-graph/affected/lock-file-changes.js +1 -0
- package/src/plugins/js/project-graph/build-dependencies/explicit-project-dependencies.js +1 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +10 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +59 -6
- package/src/plugins/js/utils/packages.js +22 -3
- package/src/plugins/js/utils/register.js +1 -0
- package/src/plugins/js/utils/typescript.js +3 -3
- package/src/plugins/package-json/create-nodes.js +3 -1
- package/src/project-graph/affected/locators/project-glob-changes.js +2 -2
- package/src/project-graph/error-types.js +32 -2
- package/src/project-graph/nx-deps-cache.js +7 -2
- package/src/project-graph/plugins/get-plugins.js +2 -1
- package/src/project-graph/plugins/in-process-loader.js +1 -1
- package/src/project-graph/plugins/isolation/plugin-worker.js +12 -6
- package/src/project-graph/plugins/loaded-nx-plugin.d.ts +2 -1
- package/src/project-graph/plugins/loaded-nx-plugin.js +3 -7
- package/src/project-graph/plugins/utils.d.ts +2 -2
- package/src/project-graph/plugins/utils.js +2 -2
- package/src/project-graph/project-graph.js +5 -2
- package/src/project-graph/utils/project-configuration-utils.d.ts +1 -1
- package/src/project-graph/utils/project-configuration-utils.js +25 -11
- package/src/project-graph/utils/retrieve-workspace-files.d.ts +1 -1
- package/src/project-graph/utils/retrieve-workspace-files.js +14 -18
- package/src/tasks-runner/batch/batch-messages.d.ts +2 -0
- package/src/tasks-runner/batch/run-batch.js +2 -3
- package/src/tasks-runner/cache.d.ts +20 -6
- package/src/tasks-runner/cache.js +104 -20
- package/src/tasks-runner/create-task-graph.d.ts +1 -1
- package/src/tasks-runner/create-task-graph.js +12 -11
- package/src/tasks-runner/default-tasks-runner.js +4 -13
- package/src/tasks-runner/forked-process-task-runner.d.ts +6 -3
- package/src/tasks-runner/forked-process-task-runner.js +29 -28
- package/src/tasks-runner/init-tasks-runner.d.ts +15 -1
- package/src/tasks-runner/init-tasks-runner.js +55 -2
- package/src/tasks-runner/is-tui-enabled.d.ts +2 -0
- package/src/tasks-runner/is-tui-enabled.js +58 -0
- package/src/tasks-runner/life-cycle.d.ts +10 -3
- package/src/tasks-runner/life-cycle.js +23 -2
- package/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +7 -2
- package/src/tasks-runner/life-cycles/task-history-life-cycle.js +6 -1
- package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +17 -0
- package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +221 -0
- package/src/tasks-runner/pseudo-terminal.d.ts +10 -7
- package/src/tasks-runner/pseudo-terminal.js +37 -35
- package/src/tasks-runner/run-command.d.ts +1 -0
- package/src/tasks-runner/run-command.js +180 -23
- package/src/tasks-runner/task-env.d.ts +1 -4
- package/src/tasks-runner/task-env.js +2 -0
- package/src/tasks-runner/task-orchestrator.d.ts +21 -9
- package/src/tasks-runner/task-orchestrator.js +126 -44
- package/src/tasks-runner/utils.d.ts +2 -2
- package/src/tasks-runner/utils.js +15 -11
- package/src/utils/child-process.d.ts +4 -0
- package/src/utils/child-process.js +23 -30
- package/src/utils/command-line-utils.d.ts +1 -1
- package/src/utils/find-matching-projects.js +2 -2
- package/src/utils/handle-errors.js +15 -0
- package/src/utils/is-ci.js +4 -1
- package/src/utils/is-using-prettier.d.ts +3 -0
- package/src/utils/is-using-prettier.js +62 -0
- package/src/utils/nx-key.d.ts +7 -0
- package/src/utils/nx-key.js +52 -0
- package/src/utils/package-manager.js +2 -2
- package/src/utils/path.js +1 -1
- package/src/utils/require-nx-key.d.ts +1 -0
- package/src/utils/require-nx-key.js +22 -0
- package/src/utils/workspace-context.d.ts +2 -0
- package/src/utils/workspace-context.js +16 -0
- package/src/command-line/activate-powerpack/activate-powerpack.d.ts +0 -2
- package/src/command-line/activate-powerpack/activate-powerpack.js +0 -34
- package/src/command-line/activate-powerpack/command-object.d.ts +0 -6
- package/src/command-line/init/implementation/react/write-craco-config.d.ts +0 -1
- package/src/command-line/init/implementation/react/write-craco-config.js +0 -61
- package/src/utils/powerpack.d.ts +0 -5
- package/src/utils/powerpack.js +0 -33
@@ -13,11 +13,12 @@ const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
|
13
13
|
const project_graph_1 = require("../../project-graph/project-graph");
|
14
14
|
const all_file_data_1 = require("../../utils/all-file-data");
|
15
15
|
const command_line_utils_1 = require("../../utils/command-line-utils");
|
16
|
-
const output_1 = require("../../utils/output");
|
17
16
|
const handle_errors_1 = require("../../utils/handle-errors");
|
17
|
+
const output_1 = require("../../utils/output");
|
18
18
|
const config_1 = require("./config/config");
|
19
19
|
const deep_merge_json_1 = require("./config/deep-merge-json");
|
20
20
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
21
|
+
const use_legacy_versioning_1 = require("./config/use-legacy-versioning");
|
21
22
|
const version_plans_1 = require("./config/version-plans");
|
22
23
|
const generate_version_plan_content_1 = require("./utils/generate-version-plan-content");
|
23
24
|
const get_touched_projects_for_group_1 = require("./utils/get-touched-projects-for-group");
|
@@ -34,7 +35,8 @@ function createAPI(overrideReleaseConfig) {
|
|
34
35
|
// Apply default configuration to any optional user configuration
|
35
36
|
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
36
37
|
if (configError) {
|
37
|
-
|
38
|
+
const USE_LEGACY_VERSIONING = (0, use_legacy_versioning_1.shouldUseLegacyVersioning)(userProvidedReleaseConfig);
|
39
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError, USE_LEGACY_VERSIONING);
|
38
40
|
}
|
39
41
|
// --print-config exits directly as it is not designed to be combined with any other programmatic operations
|
40
42
|
if (args.printConfig) {
|
@@ -210,10 +212,12 @@ async function promptForVersion(message) {
|
|
210
212
|
]);
|
211
213
|
return reply.version;
|
212
214
|
}
|
213
|
-
catch
|
215
|
+
catch {
|
214
216
|
output_1.output.log({
|
215
217
|
title: 'Cancelled version plan creation.',
|
216
218
|
});
|
219
|
+
// Ensure the cursor is always restored before exiting
|
220
|
+
process.stdout.write('\u001b[?25h');
|
217
221
|
process.exit(0);
|
218
222
|
}
|
219
223
|
}
|
@@ -4,19 +4,20 @@ exports.releasePublishCLIHandler = void 0;
|
|
4
4
|
exports.createAPI = createAPI;
|
5
5
|
const nx_json_1 = require("../../config/nx-json");
|
6
6
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
7
|
+
const tasks_execution_hooks_1 = require("../../project-graph/plugins/tasks-execution-hooks");
|
7
8
|
const project_graph_1 = require("../../project-graph/project-graph");
|
8
9
|
const run_command_1 = require("../../tasks-runner/run-command");
|
9
10
|
const command_line_utils_1 = require("../../utils/command-line-utils");
|
10
11
|
const handle_errors_1 = require("../../utils/handle-errors");
|
11
12
|
const output_1 = require("../../utils/output");
|
12
13
|
const project_graph_utils_1 = require("../../utils/project-graph-utils");
|
14
|
+
const workspace_root_1 = require("../../utils/workspace-root");
|
13
15
|
const graph_1 = require("../graph/graph");
|
14
16
|
const config_1 = require("./config/config");
|
15
17
|
const deep_merge_json_1 = require("./config/deep-merge-json");
|
16
18
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
19
|
+
const use_legacy_versioning_1 = require("./config/use-legacy-versioning");
|
17
20
|
const print_config_1 = require("./utils/print-config");
|
18
|
-
const workspace_root_1 = require("../../utils/workspace-root");
|
19
|
-
const tasks_execution_hooks_1 = require("../../project-graph/plugins/tasks-execution-hooks");
|
20
21
|
const releasePublishCLIHandler = (args) => (0, handle_errors_1.handleErrors)(args.verbose, async () => {
|
21
22
|
const publishProjectsResult = await createAPI({})(args);
|
22
23
|
// If all projects are published successfully, return 0, otherwise return 1
|
@@ -46,7 +47,8 @@ function createAPI(overrideReleaseConfig) {
|
|
46
47
|
// Apply default configuration to any optional user configuration
|
47
48
|
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
48
49
|
if (configError) {
|
49
|
-
|
50
|
+
const USE_LEGACY_VERSIONING = (0, use_legacy_versioning_1.shouldUseLegacyVersioning)(userProvidedReleaseConfig);
|
51
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError, USE_LEGACY_VERSIONING);
|
50
52
|
}
|
51
53
|
// --print-config exits directly as it is not designed to be combined with any other programmatic operations
|
52
54
|
if (args.printConfig) {
|
@@ -162,7 +164,9 @@ async function runPublishOnProjects(args, projectGraph, nxJson, projectNames, ex
|
|
162
164
|
});
|
163
165
|
/**
|
164
166
|
* Run the relevant nx-release-publish executor on each of the selected projects.
|
167
|
+
* NOTE: Force TUI to be disabled for now.
|
165
168
|
*/
|
169
|
+
process.env.NX_TUI = 'false';
|
166
170
|
const commandResults = await (0, run_command_1.runCommandForTasks)(projectsWithTarget, projectGraph, { nxJson }, {
|
167
171
|
targets: [requiredTargetName],
|
168
172
|
outputStyle: 'static',
|
@@ -7,12 +7,13 @@ const node_fs_1 = require("node:fs");
|
|
7
7
|
const nx_json_1 = require("../../config/nx-json");
|
8
8
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
9
9
|
const project_graph_1 = require("../../project-graph/project-graph");
|
10
|
-
const output_1 = require("../../utils/output");
|
11
10
|
const handle_errors_1 = require("../../utils/handle-errors");
|
11
|
+
const output_1 = require("../../utils/output");
|
12
12
|
const changelog_1 = require("./changelog");
|
13
13
|
const config_1 = require("./config/config");
|
14
14
|
const deep_merge_json_1 = require("./config/deep-merge-json");
|
15
15
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
16
|
+
const use_legacy_versioning_1 = require("./config/use-legacy-versioning");
|
16
17
|
const version_plans_1 = require("./config/version-plans");
|
17
18
|
const publish_1 = require("./publish");
|
18
19
|
const git_1 = require("./utils/git");
|
@@ -47,7 +48,8 @@ function createAPI(overrideReleaseConfig) {
|
|
47
48
|
// Apply default configuration to any optional user configuration
|
48
49
|
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
49
50
|
if (configError) {
|
50
|
-
|
51
|
+
const USE_LEGACY_VERSIONING = (0, use_legacy_versioning_1.shouldUseLegacyVersioning)(userProvidedReleaseConfig);
|
52
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError, USE_LEGACY_VERSIONING);
|
51
53
|
}
|
52
54
|
// --print-config exits directly as it is not designed to be combined with any other programmatic operations
|
53
55
|
if (args.printConfig) {
|
@@ -172,6 +174,7 @@ function createAPI(overrideReleaseConfig) {
|
|
172
174
|
await (0, git_1.gitPush)({
|
173
175
|
dryRun: args.dryRun,
|
174
176
|
verbose: args.verbose,
|
177
|
+
additionalArgs: nxReleaseConfig.git.pushArgs,
|
175
178
|
});
|
176
179
|
hasPushedChanges = true;
|
177
180
|
}
|
@@ -243,7 +246,9 @@ async function promptForPublish() {
|
|
243
246
|
]);
|
244
247
|
return reply.confirmation;
|
245
248
|
}
|
246
|
-
catch
|
249
|
+
catch {
|
250
|
+
// Ensure the cursor is always restored before exiting
|
251
|
+
process.stdout.write('\u001b[?25h');
|
247
252
|
// Handle the case where the user exits the prompt with ctrl+c
|
248
253
|
return false;
|
249
254
|
}
|
@@ -10,11 +10,14 @@ function batchProjectsByGeneratorConfig(projectGraph, releaseGroup, projectNames
|
|
10
10
|
const configBatches = new Map();
|
11
11
|
for (const projectName of projectNamesToBatch) {
|
12
12
|
const project = projectGraph.nodes[projectName];
|
13
|
-
const generator = project.data.release?.version
|
13
|
+
const generator = project.data.release?.version
|
14
|
+
?.generator ||
|
14
15
|
releaseGroup.version.generator;
|
15
16
|
const generatorOptions = {
|
16
|
-
...releaseGroup.version
|
17
|
-
|
17
|
+
...releaseGroup.version
|
18
|
+
.generatorOptions,
|
19
|
+
...project.data.release?.version
|
20
|
+
?.generatorOptions,
|
18
21
|
};
|
19
22
|
let found = false;
|
20
23
|
for (const [key, projects] of configBatches) {
|
@@ -22,7 +22,7 @@ export interface GitCommit extends RawGitCommit {
|
|
22
22
|
affectedFiles: string[];
|
23
23
|
revertedHashes: string[];
|
24
24
|
}
|
25
|
-
export declare function getLatestGitTagForPattern(releaseTagPattern: string, additionalInterpolationData?: {}): Promise<{
|
25
|
+
export declare function getLatestGitTagForPattern(releaseTagPattern: string, additionalInterpolationData?: {}, checkAllBranchesWhen?: boolean | string[]): Promise<{
|
26
26
|
tag: string;
|
27
27
|
extractedVersion: string;
|
28
28
|
} | null>;
|
@@ -50,10 +50,11 @@ export declare function gitTag({ tag, message, additionalArgs, dryRun, verbose,
|
|
50
50
|
verbose?: boolean;
|
51
51
|
logFn?: (message: string) => void;
|
52
52
|
}): Promise<string>;
|
53
|
-
export declare function gitPush({ gitRemote, dryRun, verbose, }: {
|
53
|
+
export declare function gitPush({ gitRemote, dryRun, verbose, additionalArgs, }: {
|
54
54
|
gitRemote?: string;
|
55
55
|
dryRun?: boolean;
|
56
56
|
verbose?: boolean;
|
57
|
+
additionalArgs?: string | string[];
|
57
58
|
}): Promise<void>;
|
58
59
|
export declare function parseCommits(commits: RawGitCommit[]): GitCommit[];
|
59
60
|
export declare function parseConventionalCommitsMessage(message: string): {
|
@@ -16,6 +16,7 @@ exports.getFirstGitCommit = getFirstGitCommit;
|
|
16
16
|
* https://github.com/unjs/changelogen
|
17
17
|
*/
|
18
18
|
const node_path_1 = require("node:path");
|
19
|
+
const minimatch_1 = require("minimatch");
|
19
20
|
const utils_1 = require("../../../tasks-runner/utils");
|
20
21
|
const workspace_root_1 = require("../../../utils/workspace-root");
|
21
22
|
const exec_command_1 = require("./exec-command");
|
@@ -24,22 +25,69 @@ function escapeRegExp(string) {
|
|
24
25
|
}
|
25
26
|
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
26
27
|
const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/g;
|
27
|
-
async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolationData = {}) {
|
28
|
+
async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolationData = {}, checkAllBranchesWhen) {
|
29
|
+
/**
|
30
|
+
* By default, we will try and resolve the latest match for the releaseTagPattern from the current branch,
|
31
|
+
* falling back to all branches if no match is found on the current branch.
|
32
|
+
*
|
33
|
+
* - If checkAllBranchesWhen is true it will cause us to ALWAYS check all branches for the latest match.
|
34
|
+
* - If checkAllBranchesWhen is explicitly set to false it will cause us to ONLY check the current branch for the latest match.
|
35
|
+
* - If checkAllBranchesWhen is an array of strings it will cause us to check all branches WHEN the current branch is one of the strings in the array.
|
36
|
+
*/
|
37
|
+
let alwaysCheckAllBranches = false;
|
38
|
+
if (typeof checkAllBranchesWhen !== 'undefined') {
|
39
|
+
if (typeof checkAllBranchesWhen === 'boolean') {
|
40
|
+
alwaysCheckAllBranches = checkAllBranchesWhen;
|
41
|
+
}
|
42
|
+
else if (Array.isArray(checkAllBranchesWhen)) {
|
43
|
+
/**
|
44
|
+
* Get the current git branch and determine whether to check all branches based on the checkAllBranchesWhen parameter
|
45
|
+
*/
|
46
|
+
const currentBranch = await (0, exec_command_1.execCommand)('git', [
|
47
|
+
'rev-parse',
|
48
|
+
'--abbrev-ref',
|
49
|
+
'HEAD',
|
50
|
+
]).then((r) => r.trim());
|
51
|
+
// Check exact match first
|
52
|
+
alwaysCheckAllBranches = checkAllBranchesWhen.includes(currentBranch);
|
53
|
+
// Check if any glob pattern matches next
|
54
|
+
if (!alwaysCheckAllBranches) {
|
55
|
+
alwaysCheckAllBranches = checkAllBranchesWhen.some((pattern) => {
|
56
|
+
const r = minimatch_1.minimatch.makeRe(pattern, { dot: true });
|
57
|
+
if (!r) {
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
return r.test(currentBranch);
|
61
|
+
});
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
const defaultGitArgs = [
|
66
|
+
// Apply git config to take version suffixes into account when sorting, e.g. 1.0.0 is newer than 1.0.0-beta.1
|
67
|
+
'-c',
|
68
|
+
'versionsort.suffix=-',
|
69
|
+
'tag',
|
70
|
+
'--sort',
|
71
|
+
'-v:refname',
|
72
|
+
];
|
28
73
|
try {
|
29
74
|
let tags;
|
30
75
|
tags = await (0, exec_command_1.execCommand)('git', [
|
31
|
-
|
32
|
-
'--
|
33
|
-
'-v:refname',
|
34
|
-
'--merged',
|
76
|
+
...defaultGitArgs,
|
77
|
+
...(alwaysCheckAllBranches ? [] : ['--merged']),
|
35
78
|
]).then((r) => r
|
36
79
|
.trim()
|
37
80
|
.split('\n')
|
38
81
|
.map((t) => t.trim())
|
39
82
|
.filter(Boolean));
|
40
|
-
if (
|
83
|
+
if (
|
84
|
+
// Do not run this fallback if the user explicitly set checkAllBranchesWhen to false
|
85
|
+
checkAllBranchesWhen !== false &&
|
86
|
+
!tags.length &&
|
87
|
+
// There is no point in running this fallback if we already checked against all branches
|
88
|
+
!alwaysCheckAllBranches) {
|
41
89
|
// try again, but include all tags on the repo instead of just --merged ones
|
42
|
-
tags = await (0, exec_command_1.execCommand)('git',
|
90
|
+
tags = await (0, exec_command_1.execCommand)('git', defaultGitArgs).then((r) => r
|
43
91
|
.trim()
|
44
92
|
.split('\n')
|
45
93
|
.map((t) => t.trim())
|
@@ -260,7 +308,7 @@ async function gitTag({ tag, message, additionalArgs, dryRun, verbose, logFn, })
|
|
260
308
|
throw new Error(`Unexpected error when creating tag ${tag}:\n\n${err}`);
|
261
309
|
}
|
262
310
|
}
|
263
|
-
async function gitPush({ gitRemote, dryRun, verbose, }) {
|
311
|
+
async function gitPush({ gitRemote, dryRun, verbose, additionalArgs, }) {
|
264
312
|
const commandArgs = [
|
265
313
|
'push',
|
266
314
|
// NOTE: It's important we use --follow-tags, and not --tags, so that we are precise about what we are pushing
|
@@ -270,6 +318,14 @@ async function gitPush({ gitRemote, dryRun, verbose, }) {
|
|
270
318
|
// Set custom git remote if provided
|
271
319
|
...(gitRemote ? [gitRemote] : []),
|
272
320
|
];
|
321
|
+
if (additionalArgs) {
|
322
|
+
if (Array.isArray(additionalArgs)) {
|
323
|
+
commandArgs.push(...additionalArgs);
|
324
|
+
}
|
325
|
+
else {
|
326
|
+
commandArgs.push(...additionalArgs.split(' '));
|
327
|
+
}
|
328
|
+
}
|
273
329
|
if (verbose) {
|
274
330
|
console.log(dryRun
|
275
331
|
? `Would push the current branch to the remote with the following command, but --dry-run was set:`
|
@@ -348,7 +404,7 @@ function parseGitCommit(commit, isVersionPlanCommit = false) {
|
|
348
404
|
scope: '',
|
349
405
|
references: extractReferencesFromCommitMessage(commit.message, commit.shortHash),
|
350
406
|
// The commit message is not the source of truth for a breaking (major) change in version plans, so the value is not relevant
|
351
|
-
// TODO(
|
407
|
+
// TODO(v22): Make the current GitCommit interface more clearly tied to conventional commits
|
352
408
|
isBreaking: false,
|
353
409
|
authors: getAllAuthorsForCommit(commit),
|
354
410
|
// Not applicable to version plans
|
@@ -198,7 +198,9 @@ async function promptForContinueInGitHub() {
|
|
198
198
|
]);
|
199
199
|
return reply.open === 'Yes';
|
200
200
|
}
|
201
|
-
catch
|
201
|
+
catch {
|
202
|
+
// Ensure the cursor is always restored before exiting
|
203
|
+
process.stdout.write('\u001b[?25h');
|
202
204
|
// Handle the case where the user exits the prompt with ctrl+c
|
203
205
|
process.exit(1);
|
204
206
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { ProjectGraph } from '../../../config/project-graph';
|
2
2
|
import { NxReleaseConfig } from '../config/config';
|
3
|
+
import { SemverBumpType } from '../version/version-actions';
|
3
4
|
export declare function resolveSemverSpecifierFromConventionalCommits(from: string, projectGraph: ProjectGraph, projectNames: string[], conventionalCommitsConfig: NxReleaseConfig['conventionalCommits']): Promise<string | null>;
|
4
|
-
export declare function resolveSemverSpecifierFromPrompt(selectionMessage: string, customVersionMessage: string): Promise<string>;
|
5
|
+
export declare function resolveSemverSpecifierFromPrompt(selectionMessage: string, customVersionMessage: string): Promise<SemverBumpType | string>;
|
@@ -50,7 +50,8 @@ async function resolveSemverSpecifierFromPrompt(selectionMessage, customVersionM
|
|
50
50
|
}
|
51
51
|
}
|
52
52
|
catch {
|
53
|
-
//
|
53
|
+
// Ensure the cursor is always restored before exiting
|
54
|
+
process.stdout.write('\u001b[?25h');
|
54
55
|
// We need to catch the error from enquirer prompt, otherwise yargs will print its help
|
55
56
|
process.exit(1);
|
56
57
|
}
|
@@ -7,5 +7,13 @@ import { NxReleaseConfig } from '../config/config';
|
|
7
7
|
import { GitCommit } from './git';
|
8
8
|
export declare function isRelativeVersionKeyword(val: string): val is ReleaseType;
|
9
9
|
export declare function isValidSemverSpecifier(specifier: string): boolean;
|
10
|
+
/**
|
11
|
+
* TODO: We would be able to make the logging for the conventional commits use-case
|
12
|
+
* for fixed release groups more clear/precise if we passed through which project
|
13
|
+
* the conventional commits were detected for.
|
14
|
+
*
|
15
|
+
* It would then flow up through deriveSpecifierFromConventionalCommits back to
|
16
|
+
* ReleaseGroupProcessor.
|
17
|
+
*/
|
10
18
|
export declare function determineSemverChange(commits: GitCommit[], config: NxReleaseConfig['conventionalCommits']): 'patch' | 'minor' | 'major' | null;
|
11
19
|
export declare function deriveNewSemverVersion(currentSemverVersion: string, semverSpecifier: string, preid?: string): string;
|
@@ -15,6 +15,14 @@ function isRelativeVersionKeyword(val) {
|
|
15
15
|
function isValidSemverSpecifier(specifier) {
|
16
16
|
return (specifier && !!((0, semver_1.valid)(specifier) || isRelativeVersionKeyword(specifier)));
|
17
17
|
}
|
18
|
+
/**
|
19
|
+
* TODO: We would be able to make the logging for the conventional commits use-case
|
20
|
+
* for fixed release groups more clear/precise if we passed through which project
|
21
|
+
* the conventional commits were detected for.
|
22
|
+
*
|
23
|
+
* It would then flow up through deriveSpecifierFromConventionalCommits back to
|
24
|
+
* ReleaseGroupProcessor.
|
25
|
+
*/
|
18
26
|
// https://github.com/unjs/changelogen/blob/main/src/semver.ts
|
19
27
|
function determineSemverChange(commits, config) {
|
20
28
|
let [hasMajor, hasMinor, hasPatch] = [false, false, false];
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { Tree } from '../../../generators/tree';
|
2
|
+
export type ReleaseVersionGeneratorResult = {
|
3
|
+
data: VersionData;
|
4
|
+
callback: (tree: Tree, opts: {
|
5
|
+
dryRun?: boolean;
|
6
|
+
verbose?: boolean;
|
7
|
+
generatorOptions?: Record<string, unknown>;
|
8
|
+
}) => Promise<string[] | {
|
9
|
+
changedFiles: string[];
|
10
|
+
deletedFiles: string[];
|
11
|
+
}>;
|
12
|
+
};
|
13
|
+
export type VersionData = Record<string, {
|
14
|
+
/**
|
15
|
+
* newVersion will be null in the case that no changes are detected for the project,
|
16
|
+
* e.g. when using conventional commits
|
17
|
+
*/
|
18
|
+
newVersion: string | null;
|
19
|
+
currentVersion: string;
|
20
|
+
/**
|
21
|
+
* The list of projects which depend upon the current project.
|
22
|
+
* NOTE: This is more strictly typed in versioning v2.
|
23
|
+
*/
|
24
|
+
dependentProjects: any[];
|
25
|
+
}>;
|
@@ -1,32 +1,26 @@
|
|
1
1
|
import { ProjectGraph } from '../../../config/project-graph';
|
2
|
-
import { Tree } from '../../../generators/tree';
|
3
2
|
import type { ReleaseGroupWithName } from '../config/filter-release-groups';
|
4
3
|
import { GitCommit } from './git';
|
5
4
|
export declare const noDiffInChangelogMessage: string;
|
6
|
-
export type
|
7
|
-
|
8
|
-
|
9
|
-
dryRun?: boolean;
|
10
|
-
verbose?: boolean;
|
11
|
-
generatorOptions?: Record<string, unknown>;
|
12
|
-
}) => Promise<string[] | {
|
13
|
-
changedFiles: string[];
|
14
|
-
deletedFiles: string[];
|
15
|
-
}>;
|
16
|
-
};
|
17
|
-
export type VersionData = Record<string, {
|
5
|
+
export type VersionData = Record<string, VersionDataEntry>;
|
6
|
+
export interface VersionDataEntry {
|
7
|
+
currentVersion: string;
|
18
8
|
/**
|
19
9
|
* newVersion will be null in the case that no changes are detected for the project,
|
20
10
|
* e.g. when using conventional commits
|
21
11
|
*/
|
22
12
|
newVersion: string | null;
|
23
|
-
currentVersion: string;
|
24
13
|
/**
|
25
14
|
* The list of projects which depend upon the current project.
|
26
|
-
* TODO: investigate generic type for this once more ecosystems are explored
|
27
15
|
*/
|
28
|
-
dependentProjects:
|
29
|
-
|
16
|
+
dependentProjects: {
|
17
|
+
source: string;
|
18
|
+
target: string;
|
19
|
+
type: string;
|
20
|
+
dependencyCollection: string;
|
21
|
+
rawVersionSpec: string;
|
22
|
+
}[];
|
23
|
+
}
|
30
24
|
export declare class ReleaseVersion {
|
31
25
|
rawVersion: string;
|
32
26
|
gitTag: string;
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import type { ProjectGraph, ProjectGraphProjectNode } from '../../../config/project-graph';
|
2
|
+
import { NxReleaseConfig } from '../config/config';
|
3
|
+
import { ReleaseGroupWithName } from '../config/filter-release-groups';
|
4
|
+
import { getLatestGitTagForPattern } from '../utils/git';
|
5
|
+
import { ProjectLogger } from './project-logger';
|
6
|
+
import { SemverBumpType } from './version-actions';
|
7
|
+
export declare function deriveSpecifierFromConventionalCommits(nxReleaseConfig: NxReleaseConfig, projectGraph: ProjectGraph, projectLogger: ProjectLogger, releaseGroup: ReleaseGroupWithName, projectGraphNode: ProjectGraphProjectNode, isPrerelease: boolean, latestMatchingGitTag: Awaited<ReturnType<typeof getLatestGitTagForPattern>> | undefined, fallbackCurrentVersionResolver?: 'disk', preid?: string): Promise<SemverBumpType>;
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.deriveSpecifierFromConventionalCommits = deriveSpecifierFromConventionalCommits;
|
4
|
+
const git_1 = require("../utils/git");
|
5
|
+
const resolve_semver_specifier_1 = require("../utils/resolve-semver-specifier");
|
6
|
+
async function deriveSpecifierFromConventionalCommits(nxReleaseConfig, projectGraph, projectLogger, releaseGroup, projectGraphNode,
|
7
|
+
// NOTE: This TODO was carried over from the original version generator.
|
8
|
+
//
|
9
|
+
// TODO: reevaluate this prerelease logic/workflow for independent projects
|
10
|
+
// Always assume that if the current version is a prerelease, then the next version should be a prerelease.
|
11
|
+
// Users must manually graduate from a prerelease to a release by providing an explicit specifier.
|
12
|
+
isPrerelease, latestMatchingGitTag, fallbackCurrentVersionResolver, preid) {
|
13
|
+
const affectedProjects = releaseGroup.projectsRelationship === 'independent'
|
14
|
+
? [projectGraphNode.name]
|
15
|
+
: releaseGroup.projects;
|
16
|
+
// latestMatchingGitTag will be undefined if the current version was resolved from the disk fallback.
|
17
|
+
// In this case, we want to use the first commit as the ref to be consistent with the changelog command.
|
18
|
+
const previousVersionRef = latestMatchingGitTag
|
19
|
+
? latestMatchingGitTag.tag
|
20
|
+
: fallbackCurrentVersionResolver === 'disk'
|
21
|
+
? await (0, git_1.getFirstGitCommit)()
|
22
|
+
: undefined;
|
23
|
+
if (!previousVersionRef) {
|
24
|
+
// This should never happen since the checks above should catch if the current version couldn't be resolved
|
25
|
+
throw new Error(`Unable to determine previous version ref for the projects ${affectedProjects.join(', ')}. This is likely a bug in Nx.`);
|
26
|
+
}
|
27
|
+
let specifier = await (0, resolve_semver_specifier_1.resolveSemverSpecifierFromConventionalCommits)(previousVersionRef, projectGraph, affectedProjects, nxReleaseConfig.conventionalCommits);
|
28
|
+
if (!specifier) {
|
29
|
+
projectLogger.buffer(`🚫 No changes were detected using git history and the conventional commits standard`);
|
30
|
+
return 'none';
|
31
|
+
}
|
32
|
+
// NOTE: This TODO was carried over from the original version generator.
|
33
|
+
// TODO: reevaluate this prerelease logic/workflow for independent projects
|
34
|
+
if (isPrerelease) {
|
35
|
+
specifier = 'prerelease';
|
36
|
+
projectLogger.buffer(`📄 Resolved the specifier as "${specifier}" since the current version is a prerelease`);
|
37
|
+
}
|
38
|
+
else {
|
39
|
+
let extraText = '';
|
40
|
+
if (preid && !specifier.startsWith('pre')) {
|
41
|
+
specifier = `pre${specifier}`;
|
42
|
+
extraText = `, combined with your given preid "${preid}"`;
|
43
|
+
}
|
44
|
+
projectLogger.buffer(`📄 Resolved the specifier as "${specifier}" using git history and the conventional commits standard${extraText}`);
|
45
|
+
}
|
46
|
+
return specifier;
|
47
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import type { ProjectGraphProjectNode } from '../../../config/project-graph';
|
2
|
+
import { ReleaseGroupWithName } from '../config/filter-release-groups';
|
3
|
+
import { SemverBumpType } from './version-actions';
|
4
|
+
import { ProjectLogger } from './project-logger';
|
5
|
+
export declare function deriveSpecifierFromVersionPlan(projectLogger: ProjectLogger, releaseGroup: ReleaseGroupWithName, projectGraphNode: ProjectGraphProjectNode, currentVersion: string): Promise<{
|
6
|
+
bumpType: SemverBumpType;
|
7
|
+
versionPlanPath: string;
|
8
|
+
}>;
|
@@ -0,0 +1,59 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.deriveSpecifierFromVersionPlan = deriveSpecifierFromVersionPlan;
|
4
|
+
const semver_1 = require("semver");
|
5
|
+
async function deriveSpecifierFromVersionPlan(projectLogger, releaseGroup, projectGraphNode, currentVersion) {
|
6
|
+
const projectName = projectGraphNode.name;
|
7
|
+
let bumpType = null;
|
8
|
+
let versionPlanPath = null;
|
9
|
+
if (releaseGroup.projectsRelationship === 'independent') {
|
10
|
+
const result = releaseGroup.resolvedVersionPlans.reduce((acc, plan) => {
|
11
|
+
if (!acc.spec) {
|
12
|
+
return {
|
13
|
+
spec: plan.projectVersionBumps[projectName],
|
14
|
+
path: plan.relativePath,
|
15
|
+
};
|
16
|
+
}
|
17
|
+
if (plan.projectVersionBumps[projectName]) {
|
18
|
+
const prevNewVersion = (0, semver_1.inc)(currentVersion, acc.spec);
|
19
|
+
const nextNewVersion = (0, semver_1.inc)(currentVersion, plan.projectVersionBumps[projectName]);
|
20
|
+
return (0, semver_1.gt)(nextNewVersion, prevNewVersion)
|
21
|
+
? {
|
22
|
+
spec: plan.projectVersionBumps[projectName],
|
23
|
+
path: plan.relativePath,
|
24
|
+
}
|
25
|
+
: acc;
|
26
|
+
}
|
27
|
+
return acc;
|
28
|
+
}, { spec: null, path: null });
|
29
|
+
bumpType = result.spec;
|
30
|
+
versionPlanPath = result.path;
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
const result = releaseGroup.resolvedVersionPlans.reduce((acc, plan) => {
|
34
|
+
if (!acc.spec) {
|
35
|
+
return {
|
36
|
+
spec: plan.groupVersionBump,
|
37
|
+
path: plan.relativePath,
|
38
|
+
};
|
39
|
+
}
|
40
|
+
const prevNewVersion = (0, semver_1.inc)(currentVersion, acc.spec);
|
41
|
+
const nextNewVersion = (0, semver_1.inc)(currentVersion, plan.groupVersionBump);
|
42
|
+
return (0, semver_1.gt)(nextNewVersion, prevNewVersion)
|
43
|
+
? {
|
44
|
+
spec: plan.groupVersionBump,
|
45
|
+
path: plan.relativePath,
|
46
|
+
}
|
47
|
+
: acc;
|
48
|
+
}, { spec: null, path: null });
|
49
|
+
bumpType = result.spec;
|
50
|
+
versionPlanPath = result.path;
|
51
|
+
}
|
52
|
+
if (!bumpType) {
|
53
|
+
projectLogger.buffer(`🚫 No changes were detected within version plans`);
|
54
|
+
}
|
55
|
+
return {
|
56
|
+
bumpType: bumpType ?? 'none',
|
57
|
+
versionPlanPath,
|
58
|
+
};
|
59
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ProjectLogger = void 0;
|
4
|
+
const chalk = require("chalk");
|
5
|
+
const output_1 = require("../../../utils/output");
|
6
|
+
const colors = [
|
7
|
+
{ instance: chalk.green, spinnerColor: 'green' },
|
8
|
+
{ instance: chalk.greenBright, spinnerColor: 'green' },
|
9
|
+
{ instance: chalk.red, spinnerColor: 'red' },
|
10
|
+
{ instance: chalk.redBright, spinnerColor: 'red' },
|
11
|
+
{ instance: chalk.cyan, spinnerColor: 'cyan' },
|
12
|
+
{ instance: chalk.cyanBright, spinnerColor: 'cyan' },
|
13
|
+
{ instance: chalk.yellow, spinnerColor: 'yellow' },
|
14
|
+
{ instance: chalk.yellowBright, spinnerColor: 'yellow' },
|
15
|
+
{ instance: chalk.magenta, spinnerColor: 'magenta' },
|
16
|
+
{ instance: chalk.magentaBright, spinnerColor: 'magenta' },
|
17
|
+
];
|
18
|
+
function getColor(projectName) {
|
19
|
+
let code = 0;
|
20
|
+
for (let i = 0; i < projectName.length; ++i) {
|
21
|
+
code += projectName.charCodeAt(i);
|
22
|
+
}
|
23
|
+
const colorIndex = code % colors.length;
|
24
|
+
return colors[colorIndex];
|
25
|
+
}
|
26
|
+
class ProjectLogger {
|
27
|
+
constructor(projectName) {
|
28
|
+
this.projectName = projectName;
|
29
|
+
this.logs = [];
|
30
|
+
this.color = getColor(projectName);
|
31
|
+
}
|
32
|
+
buffer(msg) {
|
33
|
+
this.logs.push(msg);
|
34
|
+
}
|
35
|
+
flush() {
|
36
|
+
if (this.logs.length === 0) {
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
output_1.output.logSingleLine(`Running release version for project: ${this.color.instance.bold(this.projectName)}`);
|
40
|
+
this.logs.forEach((msg) => {
|
41
|
+
console.log(this.color.instance.bold(this.projectName) + ' ' + msg);
|
42
|
+
});
|
43
|
+
}
|
44
|
+
}
|
45
|
+
exports.ProjectLogger = ProjectLogger;
|