nx 20.3.0-canary.20241214-4cd640a → 20.3.0-canary.20241217-ee4de0b
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/package.json +11 -11
- package/src/command-line/add/add.js +21 -45
- package/src/command-line/import/import.js +60 -34
- package/src/command-line/init/configure-plugins.d.ts +35 -0
- package/src/command-line/init/configure-plugins.js +189 -0
- package/src/command-line/init/init-v2.d.ts +1 -2
- package/src/command-line/init/init-v2.js +3 -18
- package/src/daemon/client/client.js +9 -0
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/project-graph/build-project-graph.js +57 -1
- package/src/project-graph/plugins/internal-api.d.ts +4 -3
- package/src/project-graph/plugins/internal-api.js +2 -2
- package/src/project-graph/plugins/isolation/messaging.d.ts +2 -2
- package/src/project-graph/utils/project-configuration-utils.js +31 -1
- package/src/tasks-runner/forked-process-task-runner.js +30 -8
- package/src/utils/delayed-spinner.d.ts +40 -0
- package/src/utils/delayed-spinner.js +58 -0
- package/src/command-line/import/utils/needs-install.d.ts +0 -3
- package/src/command-line/import/utils/needs-install.js +0 -31
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "20.3.0-canary.
|
3
|
+
"version": "20.3.0-canary.20241217-ee4de0b",
|
4
4
|
"private": false,
|
5
5
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
6
6
|
"repository": {
|
@@ -82,16 +82,16 @@
|
|
82
82
|
}
|
83
83
|
},
|
84
84
|
"optionalDependencies": {
|
85
|
-
"@nx/nx-darwin-arm64": "20.3.0-canary.
|
86
|
-
"@nx/nx-darwin-x64": "20.3.0-canary.
|
87
|
-
"@nx/nx-freebsd-x64": "20.3.0-canary.
|
88
|
-
"@nx/nx-linux-arm-gnueabihf": "20.3.0-canary.
|
89
|
-
"@nx/nx-linux-arm64-gnu": "20.3.0-canary.
|
90
|
-
"@nx/nx-linux-arm64-musl": "20.3.0-canary.
|
91
|
-
"@nx/nx-linux-x64-gnu": "20.3.0-canary.
|
92
|
-
"@nx/nx-linux-x64-musl": "20.3.0-canary.
|
93
|
-
"@nx/nx-win32-arm64-msvc": "20.3.0-canary.
|
94
|
-
"@nx/nx-win32-x64-msvc": "20.3.0-canary.
|
85
|
+
"@nx/nx-darwin-arm64": "20.3.0-canary.20241217-ee4de0b",
|
86
|
+
"@nx/nx-darwin-x64": "20.3.0-canary.20241217-ee4de0b",
|
87
|
+
"@nx/nx-freebsd-x64": "20.3.0-canary.20241217-ee4de0b",
|
88
|
+
"@nx/nx-linux-arm-gnueabihf": "20.3.0-canary.20241217-ee4de0b",
|
89
|
+
"@nx/nx-linux-arm64-gnu": "20.3.0-canary.20241217-ee4de0b",
|
90
|
+
"@nx/nx-linux-arm64-musl": "20.3.0-canary.20241217-ee4de0b",
|
91
|
+
"@nx/nx-linux-x64-gnu": "20.3.0-canary.20241217-ee4de0b",
|
92
|
+
"@nx/nx-linux-x64-musl": "20.3.0-canary.20241217-ee4de0b",
|
93
|
+
"@nx/nx-win32-arm64-msvc": "20.3.0-canary.20241217-ee4de0b",
|
94
|
+
"@nx/nx-win32-x64-msvc": "20.3.0-canary.20241217-ee4de0b"
|
95
95
|
},
|
96
96
|
"nx-migrations": {
|
97
97
|
"migrations": "./migrations.json",
|
@@ -5,7 +5,7 @@ exports.addHandler = addHandler;
|
|
5
5
|
const child_process_1 = require("child_process");
|
6
6
|
const fs_1 = require("fs");
|
7
7
|
const ora = require("ora");
|
8
|
-
const
|
8
|
+
const yargsParser = require("yargs-parser");
|
9
9
|
const nx_json_1 = require("../../config/nx-json");
|
10
10
|
const child_process_2 = require("../../utils/child-process");
|
11
11
|
const fileutils_1 = require("../../utils/fileutils");
|
@@ -13,11 +13,11 @@ const logger_1 = require("../../utils/logger");
|
|
13
13
|
const output_1 = require("../../utils/output");
|
14
14
|
const package_manager_1 = require("../../utils/package-manager");
|
15
15
|
const handle_errors_1 = require("../../utils/handle-errors");
|
16
|
-
const plugins_1 = require("../../utils/plugins");
|
17
16
|
const versions_1 = require("../../utils/versions");
|
18
17
|
const workspace_root_1 = require("../../utils/workspace-root");
|
19
18
|
const add_nx_scripts_1 = require("../init/implementation/dot-nx/add-nx-scripts");
|
20
19
|
const semver_1 = require("semver");
|
20
|
+
const configure_plugins_1 = require("../init/configure-plugins");
|
21
21
|
function addHandler(options) {
|
22
22
|
return (0, handle_errors_1.handleErrors)(options.verbose, async () => {
|
23
23
|
output_1.output.addNewline();
|
@@ -79,63 +79,39 @@ async function installPackage(pkgName, version, nxJson) {
|
|
79
79
|
spinner.succeed();
|
80
80
|
}
|
81
81
|
async function initializePlugin(pkgName, options, nxJson) {
|
82
|
-
const
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
82
|
+
const parsedCommandArgs = yargsParser(options.__overrides_unparsed__, {
|
83
|
+
configuration: {
|
84
|
+
'parse-numbers': false,
|
85
|
+
'parse-positional-numbers': false,
|
86
|
+
'dot-notation': false,
|
87
|
+
'camel-case-expansion': false,
|
88
|
+
},
|
89
|
+
});
|
90
|
+
if (exports.coreNxPluginVersions.has(pkgName)) {
|
91
|
+
parsedCommandArgs.keepExistingVersions = true;
|
92
|
+
if (options.updatePackageScripts ||
|
93
|
+
(options.updatePackageScripts === undefined &&
|
94
|
+
nxJson.useInferencePlugins !== false &&
|
95
|
+
process.env.NX_ADD_PLUGINS !== 'false')) {
|
96
|
+
parsedCommandArgs.updatePackageScripts = true;
|
97
|
+
}
|
96
98
|
}
|
97
99
|
const spinner = ora(`Initializing ${pkgName}...`);
|
98
100
|
spinner.start();
|
99
101
|
try {
|
100
|
-
|
101
|
-
if (exports.coreNxPluginVersions.has(pkgName)) {
|
102
|
-
args.push(`--keepExistingVersions`);
|
103
|
-
if (options.updatePackageScripts ||
|
104
|
-
(options.updatePackageScripts === undefined &&
|
105
|
-
nxJson.useInferencePlugins !== false &&
|
106
|
-
process.env.NX_ADD_PLUGINS !== 'false')) {
|
107
|
-
args.push(`--updatePackageScripts`);
|
108
|
-
}
|
109
|
-
}
|
110
|
-
if (options.__overrides_unparsed__.length) {
|
111
|
-
args.push(...options.__overrides_unparsed__);
|
112
|
-
}
|
113
|
-
(0, child_process_2.runNxSync)(`g ${pkgName}:${initGenerator} ${args.join(' ')}`, {
|
114
|
-
stdio: [0, 1, 2],
|
115
|
-
});
|
102
|
+
await (0, configure_plugins_1.installPlugin)(pkgName, workspace_root_1.workspaceRoot, options.verbose, parsedCommandArgs);
|
116
103
|
}
|
117
104
|
catch (e) {
|
118
105
|
spinner.fail();
|
119
106
|
output_1.output.addNewline();
|
120
|
-
logger_1.logger.error(e);
|
121
107
|
output_1.output.error({
|
122
|
-
title: `Failed to initialize ${pkgName}
|
108
|
+
title: `Failed to initialize ${pkgName}`,
|
109
|
+
bodyLines: (0, configure_plugins_1.getFailedToInstallPluginErrorMessages)(e),
|
123
110
|
});
|
124
111
|
process.exit(1);
|
125
112
|
}
|
126
113
|
spinner.succeed();
|
127
114
|
}
|
128
|
-
function findInitGenerator(generators) {
|
129
|
-
if (generators['init']) {
|
130
|
-
return 'init';
|
131
|
-
}
|
132
|
-
const angularPluginInstalled = (0, angular_json_1.isAngularPluginInstalled)();
|
133
|
-
if (angularPluginInstalled && generators['ng-add']) {
|
134
|
-
return 'ng-add';
|
135
|
-
}
|
136
|
-
return Object.keys(generators).find((name) => generators[name].aliases?.includes('init') ||
|
137
|
-
(angularPluginInstalled && generators[name].aliases?.includes('ng-add')));
|
138
|
-
}
|
139
115
|
function parsePackageSpecifier(packageSpecifier) {
|
140
116
|
const i = packageSpecifier.lastIndexOf('@');
|
141
117
|
if (i <= 0) {
|
@@ -19,12 +19,12 @@ const utils_1 = require("../init/implementation/utils");
|
|
19
19
|
const command_line_utils_1 = require("../../utils/command-line-utils");
|
20
20
|
const prepare_source_repo_1 = require("./utils/prepare-source-repo");
|
21
21
|
const merge_remote_source_1 = require("./utils/merge-remote-source");
|
22
|
-
const needs_install_1 = require("./utils/needs-install");
|
23
22
|
const minimatch_1 = require("minimatch");
|
23
|
+
const configure_plugins_1 = require("../init/configure-plugins");
|
24
24
|
const importRemoteName = '__tmp_nx_import__';
|
25
25
|
async function importHandler(options) {
|
26
26
|
process.env.NX_RUNNING_NX_IMPORT = 'true';
|
27
|
-
let { sourceRepository, ref, source, destination } = options;
|
27
|
+
let { sourceRepository, ref, source, destination, verbose } = options;
|
28
28
|
const destinationGitClient = new git_utils_1.GitRepository(process.cwd());
|
29
29
|
if (await destinationGitClient.hasUncommittedChanges()) {
|
30
30
|
throw new Error(`You have uncommitted changes in the destination repository. Commit or revert the changes and try again.`);
|
@@ -141,7 +141,6 @@ async function importHandler(options) {
|
|
141
141
|
throw new Error(`The source directory ${source} does not exist in ${sourceRepository}. Please double check to make sure it exists.`);
|
142
142
|
}
|
143
143
|
const packageManager = (0, package_manager_1.detectPackageManager)(workspace_root_1.workspaceRoot);
|
144
|
-
const originalPackageWorkspaces = await (0, needs_install_1.getPackagesInPackageManagerWorkspace)(packageManager);
|
145
144
|
const sourceIsNxWorkspace = (0, node_fs_1.existsSync)((0, path_1.join)(sourceGitClient.root, 'nx.json'));
|
146
145
|
const relativeDestination = (0, path_1.relative)(destinationGitClient.root, absDestination);
|
147
146
|
await (0, prepare_source_repo_1.prepareSourceRepo)(sourceGitClient, ref, source, relativeDestination, tempImportBranch, sourceRepository);
|
@@ -165,40 +164,18 @@ async function importHandler(options) {
|
|
165
164
|
});
|
166
165
|
}
|
167
166
|
await handleMissingWorkspacesEntry(packageManager, pmc, relativeDestination, destinationGitClient);
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
catch (e) {
|
177
|
-
installFailed = true;
|
178
|
-
output_1.output.error({
|
179
|
-
title: `Install failed: ${e.message || 'Unknown error'}`,
|
180
|
-
bodyLines: [e.stack],
|
181
|
-
});
|
182
|
-
}
|
183
|
-
}
|
184
|
-
else if (await (0, needs_install_1.needsInstall)(packageManager, originalPackageWorkspaces)) {
|
185
|
-
try {
|
186
|
-
output_1.output.log({
|
187
|
-
title: 'Installing dependencies for imported code',
|
188
|
-
});
|
189
|
-
(0, utils_1.runInstall)(workspace_root_1.workspaceRoot, (0, package_manager_1.getPackageManagerCommand)(packageManager));
|
190
|
-
await destinationGitClient.amendCommit();
|
191
|
-
}
|
192
|
-
catch (e) {
|
193
|
-
installFailed = true;
|
194
|
-
output_1.output.error({
|
195
|
-
title: `Install failed: ${e.message || 'Unknown error'}`,
|
196
|
-
bodyLines: [e.stack],
|
197
|
-
});
|
167
|
+
let installed = await runInstallDestinationRepo(packageManager, destinationGitClient);
|
168
|
+
if (installed && plugins.length > 0) {
|
169
|
+
installed = await runPluginsInstall(plugins, pmc, destinationGitClient);
|
170
|
+
if (installed) {
|
171
|
+
const { succeededPlugins } = await (0, configure_plugins_1.configurePlugins)(plugins, updatePackageScripts, pmc, workspace_root_1.workspaceRoot, verbose);
|
172
|
+
if (succeededPlugins.length > 0) {
|
173
|
+
await destinationGitClient.amendCommit();
|
174
|
+
}
|
198
175
|
}
|
199
176
|
}
|
200
177
|
console.log(await destinationGitClient.showStat());
|
201
|
-
if (
|
178
|
+
if (installed === false) {
|
202
179
|
const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager);
|
203
180
|
output_1.output.warn({
|
204
181
|
title: `The import was successful, but the install failed`,
|
@@ -258,6 +235,55 @@ async function createTemporaryRemote(destinationGitClient, sourceRemoteUrl, remo
|
|
258
235
|
await destinationGitClient.fetch(remoteName);
|
259
236
|
}
|
260
237
|
/**
|
238
|
+
* Run install for the imported code and plugins
|
239
|
+
* @returns true if the install failed
|
240
|
+
*/
|
241
|
+
async function runInstallDestinationRepo(packageManager, destinationGitClient) {
|
242
|
+
let installed = true;
|
243
|
+
try {
|
244
|
+
output_1.output.log({
|
245
|
+
title: 'Installing dependencies for imported code',
|
246
|
+
});
|
247
|
+
(0, utils_1.runInstall)(workspace_root_1.workspaceRoot, (0, package_manager_1.getPackageManagerCommand)(packageManager));
|
248
|
+
await destinationGitClient.amendCommit();
|
249
|
+
}
|
250
|
+
catch (e) {
|
251
|
+
installed = false;
|
252
|
+
output_1.output.error({
|
253
|
+
title: `Install failed: ${e.message || 'Unknown error'}`,
|
254
|
+
bodyLines: [e.stack],
|
255
|
+
});
|
256
|
+
}
|
257
|
+
return installed;
|
258
|
+
}
|
259
|
+
async function runPluginsInstall(plugins, pmc, destinationGitClient) {
|
260
|
+
let installed = true;
|
261
|
+
output_1.output.log({ title: 'Installing Plugins' });
|
262
|
+
try {
|
263
|
+
(0, configure_plugins_1.runPackageManagerInstallPlugins)(workspace_root_1.workspaceRoot, pmc, plugins);
|
264
|
+
await destinationGitClient.amendCommit();
|
265
|
+
}
|
266
|
+
catch (e) {
|
267
|
+
installed = false;
|
268
|
+
output_1.output.error({
|
269
|
+
title: `Install failed: ${e.message || 'Unknown error'}`,
|
270
|
+
bodyLines: [
|
271
|
+
'The following plugins were not installed:',
|
272
|
+
...plugins.map((p) => `- ${chalk.bold(p)}`),
|
273
|
+
e.stack,
|
274
|
+
],
|
275
|
+
});
|
276
|
+
output_1.output.error({
|
277
|
+
title: `To install the plugins manually`,
|
278
|
+
bodyLines: [
|
279
|
+
'You may need to run commands to install the plugins:',
|
280
|
+
...plugins.map((p) => `- ${chalk.bold(pmc.exec + ' nx add ' + p)}`),
|
281
|
+
],
|
282
|
+
});
|
283
|
+
}
|
284
|
+
return installed;
|
285
|
+
}
|
286
|
+
/*
|
261
287
|
* If the user imports a project that isn't in the workspaces entry, we should add that path to the workspaces entry.
|
262
288
|
*/
|
263
289
|
async function handleMissingWorkspacesEntry(pm, pmc, pkgPath, destinationGitClient) {
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { PackageManagerCommands } from '../../utils/package-manager';
|
2
|
+
export declare function runPackageManagerInstallPlugins(repoRoot: string, pmc: PackageManagerCommands, plugins: string[]): void;
|
3
|
+
/**
|
4
|
+
* Installs a plugin by running its init generator. It will change the file system tree passed in.
|
5
|
+
* @param plugin The name of the plugin to install
|
6
|
+
* @param repoRoot repo root
|
7
|
+
* @param verbose verbose
|
8
|
+
* @param options options passed to init generator
|
9
|
+
* @returns void
|
10
|
+
*/
|
11
|
+
export declare function installPlugin(plugin: string, repoRoot: string, verbose: boolean, options: {
|
12
|
+
[k: string]: any;
|
13
|
+
}): Promise<void>;
|
14
|
+
/**
|
15
|
+
* Install plugins
|
16
|
+
* Get the implementation of the plugin's init generator and run it
|
17
|
+
* @returns a list of succeeded plugins and a map of failed plugins to errors
|
18
|
+
*/
|
19
|
+
export declare function installPlugins(plugins: string[], updatePackageScripts: boolean, repoRoot?: string, verbose?: boolean): Promise<{
|
20
|
+
succeededPlugins: string[];
|
21
|
+
failedPlugins: {
|
22
|
+
[plugin: string]: Error;
|
23
|
+
};
|
24
|
+
}>;
|
25
|
+
/**
|
26
|
+
* Configures plugins, installs them, and outputs the results
|
27
|
+
* @returns a list of succeeded plugins and a map of failed plugins to errors
|
28
|
+
*/
|
29
|
+
export declare function configurePlugins(plugins: string[], updatePackageScripts: boolean, pmc: PackageManagerCommands, repoRoot?: string, verbose?: boolean): Promise<{
|
30
|
+
succeededPlugins: string[];
|
31
|
+
failedPlugins: {
|
32
|
+
[plugin: string]: Error;
|
33
|
+
};
|
34
|
+
}>;
|
35
|
+
export declare function getFailedToInstallPluginErrorMessages(e: any): string[];
|
@@ -0,0 +1,189 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.runPackageManagerInstallPlugins = runPackageManagerInstallPlugins;
|
4
|
+
exports.installPlugin = installPlugin;
|
5
|
+
exports.installPlugins = installPlugins;
|
6
|
+
exports.configurePlugins = configurePlugins;
|
7
|
+
exports.getFailedToInstallPluginErrorMessages = getFailedToInstallPluginErrorMessages;
|
8
|
+
const createSpinner = require("ora");
|
9
|
+
const chalk_1 = require("chalk");
|
10
|
+
const package_manager_1 = require("../../utils/package-manager");
|
11
|
+
const output_1 = require("../../utils/output");
|
12
|
+
const tree_1 = require("../../generators/tree");
|
13
|
+
const generator_utils_1 = require("../generate/generator-utils");
|
14
|
+
const workspace_root_1 = require("../../utils/workspace-root");
|
15
|
+
const utils_1 = require("./implementation/utils");
|
16
|
+
const plugins_1 = require("../../utils/plugins");
|
17
|
+
const angular_json_1 = require("../../adapter/angular-json");
|
18
|
+
const error_types_1 = require("../../project-graph/error-types");
|
19
|
+
function runPackageManagerInstallPlugins(repoRoot, pmc = (0, package_manager_1.getPackageManagerCommand)(), plugins) {
|
20
|
+
if (plugins.length === 0) {
|
21
|
+
return;
|
22
|
+
}
|
23
|
+
(0, utils_1.addDepsToPackageJson)(repoRoot, plugins);
|
24
|
+
(0, utils_1.runInstall)(repoRoot, pmc);
|
25
|
+
}
|
26
|
+
/**
|
27
|
+
* Installs a plugin by running its init generator. It will change the file system tree passed in.
|
28
|
+
* @param plugin The name of the plugin to install
|
29
|
+
* @param repoRoot repo root
|
30
|
+
* @param verbose verbose
|
31
|
+
* @param options options passed to init generator
|
32
|
+
* @returns void
|
33
|
+
*/
|
34
|
+
async function installPlugin(plugin, repoRoot = workspace_root_1.workspaceRoot, verbose = false, options) {
|
35
|
+
const host = new tree_1.FsTree(repoRoot, verbose, `install ${plugin}`);
|
36
|
+
const capabilities = await (0, plugins_1.getPluginCapabilities)(repoRoot, plugin, {});
|
37
|
+
const generators = capabilities?.generators;
|
38
|
+
if (!generators) {
|
39
|
+
throw new Error(`No generators found in ${plugin}.`);
|
40
|
+
}
|
41
|
+
const initGenerator = findInitGenerator(generators);
|
42
|
+
if (!initGenerator) {
|
43
|
+
output_1.output.log({
|
44
|
+
title: `No "init" generator found in ${plugin}. Skipping initialization.`,
|
45
|
+
});
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
const { implementationFactory } = (0, generator_utils_1.getGeneratorInformation)(plugin, initGenerator, repoRoot, {});
|
49
|
+
const implementation = implementationFactory();
|
50
|
+
const task = await implementation(host, options);
|
51
|
+
(0, tree_1.flushChanges)(repoRoot, host.listChanges());
|
52
|
+
if (task) {
|
53
|
+
await task();
|
54
|
+
}
|
55
|
+
}
|
56
|
+
/**
|
57
|
+
* Install plugins
|
58
|
+
* Get the implementation of the plugin's init generator and run it
|
59
|
+
* @returns a list of succeeded plugins and a map of failed plugins to errors
|
60
|
+
*/
|
61
|
+
async function installPlugins(plugins, updatePackageScripts, repoRoot = workspace_root_1.workspaceRoot, verbose = false) {
|
62
|
+
if (plugins.length === 0) {
|
63
|
+
return {
|
64
|
+
succeededPlugins: [],
|
65
|
+
failedPlugins: {},
|
66
|
+
};
|
67
|
+
}
|
68
|
+
const spinner = createSpinner();
|
69
|
+
let succeededPlugins = [];
|
70
|
+
const failedPlugins = {};
|
71
|
+
for (const plugin of plugins) {
|
72
|
+
try {
|
73
|
+
spinner.start('Installing plugin ' + plugin);
|
74
|
+
await installPlugin(plugin, repoRoot, verbose, {
|
75
|
+
keepExistingVersions: true,
|
76
|
+
updatePackageScripts,
|
77
|
+
addPlugin: true,
|
78
|
+
skipFormat: false,
|
79
|
+
skipPackageJson: false,
|
80
|
+
});
|
81
|
+
succeededPlugins.push(plugin);
|
82
|
+
spinner.succeed('Installed plugin ' + plugin);
|
83
|
+
}
|
84
|
+
catch (e) {
|
85
|
+
failedPlugins[plugin] = e;
|
86
|
+
spinner.fail('Failed to install plugin ' + plugin);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return {
|
90
|
+
succeededPlugins,
|
91
|
+
failedPlugins,
|
92
|
+
};
|
93
|
+
}
|
94
|
+
/**
|
95
|
+
* Configures plugins, installs them, and outputs the results
|
96
|
+
* @returns a list of succeeded plugins and a map of failed plugins to errors
|
97
|
+
*/
|
98
|
+
async function configurePlugins(plugins, updatePackageScripts, pmc, repoRoot = workspace_root_1.workspaceRoot, verbose = false) {
|
99
|
+
if (plugins.length === 0) {
|
100
|
+
return {
|
101
|
+
succeededPlugins: [],
|
102
|
+
failedPlugins: {},
|
103
|
+
};
|
104
|
+
}
|
105
|
+
output_1.output.log({ title: '🔨 Configuring plugins' });
|
106
|
+
let { succeededPlugins, failedPlugins } = await installPlugins(plugins, updatePackageScripts, repoRoot, verbose);
|
107
|
+
if (succeededPlugins.length > 0) {
|
108
|
+
output_1.output.success({
|
109
|
+
title: 'Installed Plugins',
|
110
|
+
bodyLines: succeededPlugins.map((p) => `- ${(0, chalk_1.bold)(p)}`),
|
111
|
+
});
|
112
|
+
}
|
113
|
+
if (Object.keys(failedPlugins).length > 0) {
|
114
|
+
output_1.output.error({
|
115
|
+
title: `Failed to install plugins`,
|
116
|
+
bodyLines: [
|
117
|
+
'The following plugins were not installed:',
|
118
|
+
...Object.keys(failedPlugins).map((p) => `- ${(0, chalk_1.bold)(p)}`),
|
119
|
+
],
|
120
|
+
});
|
121
|
+
Object.entries(failedPlugins).forEach(([plugin, error]) => {
|
122
|
+
output_1.output.error({
|
123
|
+
title: `Failed to install ${plugin}`,
|
124
|
+
bodyLines: getFailedToInstallPluginErrorMessages(error),
|
125
|
+
});
|
126
|
+
});
|
127
|
+
output_1.output.error({
|
128
|
+
title: `To install the plugins manually`,
|
129
|
+
bodyLines: [
|
130
|
+
'You may need to run commands to install the plugins:',
|
131
|
+
...Object.keys(failedPlugins).map((p) => `- ${(0, chalk_1.bold)(pmc.exec + ' nx add ' + p)}`),
|
132
|
+
],
|
133
|
+
});
|
134
|
+
}
|
135
|
+
return { succeededPlugins, failedPlugins };
|
136
|
+
}
|
137
|
+
function findInitGenerator(generators) {
|
138
|
+
if (generators['init']) {
|
139
|
+
return 'init';
|
140
|
+
}
|
141
|
+
const angularPluginInstalled = (0, angular_json_1.isAngularPluginInstalled)();
|
142
|
+
if (angularPluginInstalled && generators['ng-add']) {
|
143
|
+
return 'ng-add';
|
144
|
+
}
|
145
|
+
return Object.keys(generators).find((name) => generators[name].aliases?.includes('init') ||
|
146
|
+
(angularPluginInstalled && generators[name].aliases?.includes('ng-add')));
|
147
|
+
}
|
148
|
+
function getFailedToInstallPluginErrorMessages(e) {
|
149
|
+
const errorBodyLines = [];
|
150
|
+
if ((0, error_types_1.isProjectConfigurationsError)(e) && e.errors.length > 0) {
|
151
|
+
for (const error of e.errors) {
|
152
|
+
if ((0, error_types_1.isAggregateCreateNodesError)(error)) {
|
153
|
+
const innerErrors = error.errors;
|
154
|
+
for (const [file, e] of innerErrors) {
|
155
|
+
if (file) {
|
156
|
+
errorBodyLines.push(` - ${(0, chalk_1.bold)(file)}: ${e.message}`);
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
errorBodyLines.push(` - ${e.message}`);
|
160
|
+
}
|
161
|
+
if (e.stack) {
|
162
|
+
const innerStackTrace = ' ' + e.stack.split('\n')?.join('\n ');
|
163
|
+
errorBodyLines.push(innerStackTrace);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
else if (!(0, error_types_1.isProjectsWithNoNameError)(error)) {
|
168
|
+
// swallow ProjectsWithNameError
|
169
|
+
if (error.message) {
|
170
|
+
errorBodyLines.push(` - ${error.message}`);
|
171
|
+
}
|
172
|
+
if (error.stack) {
|
173
|
+
const innerStackTrace = ' ' + error.stack.split('\n')?.join('\n ');
|
174
|
+
errorBodyLines.push(innerStackTrace);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
else {
|
180
|
+
if (e.message) {
|
181
|
+
errorBodyLines.push(` - ${e.message}`);
|
182
|
+
}
|
183
|
+
if (e.stack) {
|
184
|
+
const innerStackTrace = ' ' + e.stack.split('\n')?.join('\n ');
|
185
|
+
errorBodyLines.push(innerStackTrace);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
return errorBodyLines;
|
189
|
+
}
|
@@ -1,12 +1,11 @@
|
|
1
|
-
import { PackageManagerCommands } from '../../utils/package-manager';
|
2
1
|
import { NxJsonConfiguration } from '../../config/nx-json';
|
3
2
|
export interface InitArgs {
|
4
3
|
interactive: boolean;
|
5
4
|
nxCloud?: boolean;
|
6
5
|
useDotNxInstallation?: boolean;
|
7
6
|
integrated?: boolean;
|
7
|
+
verbose?: boolean;
|
8
8
|
}
|
9
|
-
export declare function installPlugins(repoRoot: string, plugins: string[], pmc: PackageManagerCommands, updatePackageScripts: boolean): void;
|
10
9
|
export declare function initHandler(options: InitArgs): Promise<void>;
|
11
10
|
export declare function detectPlugins(nxJson: NxJsonConfiguration, interactive: boolean, includeAngularCli?: boolean): Promise<{
|
12
11
|
plugins: string[];
|
@@ -1,6 +1,5 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.installPlugins = installPlugins;
|
4
3
|
exports.initHandler = initHandler;
|
5
4
|
exports.detectPlugins = detectPlugins;
|
6
5
|
const fs_1 = require("fs");
|
@@ -13,7 +12,6 @@ const fileutils_1 = require("../../utils/fileutils");
|
|
13
12
|
const versions_1 = require("../../utils/versions");
|
14
13
|
const utils_1 = require("./implementation/utils");
|
15
14
|
const enquirer_1 = require("enquirer");
|
16
|
-
const child_process_2 = require("child_process");
|
17
15
|
const angular_1 = require("./implementation/angular");
|
18
16
|
const workspace_context_1 = require("../../utils/workspace-context");
|
19
17
|
const connect_to_nx_cloud_1 = require("../connect/connect-to-nx-cloud");
|
@@ -21,21 +19,7 @@ const add_nx_to_npm_repo_1 = require("./implementation/add-nx-to-npm-repo");
|
|
21
19
|
const add_nx_to_monorepo_1 = require("./implementation/add-nx-to-monorepo");
|
22
20
|
const nx_json_1 = require("../../config/nx-json");
|
23
21
|
const get_package_name_from_import_path_1 = require("../../utils/get-package-name-from-import-path");
|
24
|
-
|
25
|
-
if (plugins.length === 0) {
|
26
|
-
return;
|
27
|
-
}
|
28
|
-
(0, utils_1.addDepsToPackageJson)(repoRoot, plugins);
|
29
|
-
(0, utils_1.runInstall)(repoRoot, pmc);
|
30
|
-
output_1.output.log({ title: '🔨 Configuring plugins' });
|
31
|
-
for (const plugin of plugins) {
|
32
|
-
(0, child_process_2.execSync)(`${pmc.exec} nx g ${plugin}:init --keepExistingVersions ${updatePackageScripts ? '--updatePackageScripts' : ''}`, {
|
33
|
-
stdio: [0, 1, 2],
|
34
|
-
cwd: repoRoot,
|
35
|
-
windowsHide: false,
|
36
|
-
});
|
37
|
-
}
|
38
|
-
}
|
22
|
+
const configure_plugins_1 = require("./configure-plugins");
|
39
23
|
async function initHandler(options) {
|
40
24
|
process.env.NX_RUNNING_NX_INIT = 'true';
|
41
25
|
const version = process.env.NX_VERSION ?? ((0, semver_1.prerelease)(versions_1.nxVersion) ? 'next' : 'latest');
|
@@ -98,7 +82,8 @@ async function initHandler(options) {
|
|
98
82
|
output_1.output.log({ title: '🧐 Checking dependencies' });
|
99
83
|
const { plugins, updatePackageScripts } = await detectPlugins(nxJson, options.interactive);
|
100
84
|
output_1.output.log({ title: '📦 Installing Nx' });
|
101
|
-
|
85
|
+
(0, configure_plugins_1.runPackageManagerInstallPlugins)(repoRoot, pmc, plugins);
|
86
|
+
await (0, configure_plugins_1.configurePlugins)(plugins, updatePackageScripts, pmc, repoRoot, options.verbose);
|
102
87
|
if (useNxCloud) {
|
103
88
|
output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
|
104
89
|
await (0, utils_1.initCloud)('nx-init');
|
@@ -30,6 +30,7 @@ const get_sync_generator_changes_1 = require("../message-types/get-sync-generato
|
|
30
30
|
const get_registered_sync_generators_1 = require("../message-types/get-registered-sync-generators");
|
31
31
|
const update_workspace_context_1 = require("../message-types/update-workspace-context");
|
32
32
|
const flush_sync_generator_changes_to_disk_1 = require("../message-types/flush-sync-generator-changes-to-disk");
|
33
|
+
const delayed_spinner_1 = require("../../utils/delayed-spinner");
|
33
34
|
const DAEMON_ENV_SETTINGS = {
|
34
35
|
NX_PROJECT_GLOB_CACHE: 'false',
|
35
36
|
NX_CACHE_PROJECTS_CONFIG: 'false',
|
@@ -113,6 +114,11 @@ class DaemonClient {
|
|
113
114
|
return this.sendToDaemonViaQueue({ type: 'REQUEST_SHUTDOWN' });
|
114
115
|
}
|
115
116
|
async getProjectGraphAndSourceMaps() {
|
117
|
+
let spinner;
|
118
|
+
if (delayed_spinner_1.SHOULD_SHOW_SPINNERS) {
|
119
|
+
// If the graph takes a while to load, we want to show a spinner.
|
120
|
+
spinner = new delayed_spinner_1.DelayedSpinner('Calculating the project graph on the Nx Daemon', 500).scheduleMessageUpdate('Calculating the project graph on the Nx Daemon is taking longer than expected. Re-run with NX_DAEMON=false to see more details.', 30_000);
|
121
|
+
}
|
116
122
|
try {
|
117
123
|
const response = await this.sendToDaemonViaQueue({
|
118
124
|
type: 'REQUEST_PROJECT_GRAPH',
|
@@ -130,6 +136,9 @@ class DaemonClient {
|
|
130
136
|
throw e;
|
131
137
|
}
|
132
138
|
}
|
139
|
+
finally {
|
140
|
+
spinner?.cleanup();
|
141
|
+
}
|
133
142
|
}
|
134
143
|
async getAllFileData() {
|
135
144
|
return await this.sendToDaemonViaQueue({ type: 'REQUEST_FILE_DATA' });
|
Binary file
|
@@ -18,6 +18,7 @@ const configuration_1 = require("../config/configuration");
|
|
18
18
|
const fs_1 = require("fs");
|
19
19
|
const error_types_1 = require("./error-types");
|
20
20
|
const project_configuration_utils_1 = require("./utils/project-configuration-utils");
|
21
|
+
const delayed_spinner_1 = require("../utils/delayed-spinner");
|
21
22
|
let storedFileMap = null;
|
22
23
|
let storedAllWorkspaceFiles = null;
|
23
24
|
let storedRustReferences = null;
|
@@ -186,11 +187,39 @@ async function updateProjectGraphWithPlugins(context, initProjectGraph, plugins,
|
|
186
187
|
const builder = new project_graph_builder_1.ProjectGraphBuilder(graph, context.fileMap.projectFileMap, context.fileMap.nonProjectFiles);
|
187
188
|
const createDependencyPlugins = plugins.filter((plugin) => plugin.createDependencies);
|
188
189
|
perf_hooks_1.performance.mark('createDependencies:start');
|
190
|
+
let spinner;
|
191
|
+
const inProgressPlugins = new Set();
|
192
|
+
function updateSpinner() {
|
193
|
+
if (!spinner) {
|
194
|
+
return;
|
195
|
+
}
|
196
|
+
if (inProgressPlugins.size === 1) {
|
197
|
+
return `Creating project graph dependencies with ${inProgressPlugins.keys()[0]}`;
|
198
|
+
}
|
199
|
+
else if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
200
|
+
return [
|
201
|
+
`Creating project graph dependencies with ${inProgressPlugins.size} plugins`,
|
202
|
+
...Array.from(inProgressPlugins).map((p) => ` - ${p}`),
|
203
|
+
].join('\n');
|
204
|
+
}
|
205
|
+
else {
|
206
|
+
return `Creating project graph dependencies with ${inProgressPlugins.size} plugins`;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
if (delayed_spinner_1.SHOULD_SHOW_SPINNERS) {
|
210
|
+
spinner = new delayed_spinner_1.DelayedSpinner(`Creating project graph dependencies with ${plugins.length} plugins`);
|
211
|
+
}
|
189
212
|
await Promise.all(createDependencyPlugins.map(async (plugin) => {
|
190
213
|
perf_hooks_1.performance.mark(`${plugin.name}:createDependencies - start`);
|
214
|
+
inProgressPlugins.add(plugin.name);
|
191
215
|
try {
|
192
|
-
const dependencies = await plugin
|
216
|
+
const dependencies = await plugin
|
217
|
+
.createDependencies({
|
193
218
|
...context,
|
219
|
+
})
|
220
|
+
.finally(() => {
|
221
|
+
inProgressPlugins.delete(plugin.name);
|
222
|
+
updateSpinner();
|
194
223
|
});
|
195
224
|
for (const dep of dependencies) {
|
196
225
|
builder.addDependency(dep.source, dep.target, dep.type, 'sourceFile' in dep ? dep.sourceFile : null);
|
@@ -206,6 +235,7 @@ async function updateProjectGraphWithPlugins(context, initProjectGraph, plugins,
|
|
206
235
|
}));
|
207
236
|
perf_hooks_1.performance.mark('createDependencies:end');
|
208
237
|
perf_hooks_1.performance.measure(`createDependencies`, `createDependencies:start`, `createDependencies:end`);
|
238
|
+
spinner?.cleanup();
|
209
239
|
const graphWithDeps = builder.getUpdatedProjectGraph();
|
210
240
|
const { errors: metadataErrors, graph: updatedGraph } = await applyProjectMetadata(graphWithDeps, plugins, {
|
211
241
|
nxJsonConfiguration: context.nxJsonConfiguration,
|
@@ -232,9 +262,32 @@ async function applyProjectMetadata(graph, plugins, context, sourceMap) {
|
|
232
262
|
const results = [];
|
233
263
|
const errors = [];
|
234
264
|
perf_hooks_1.performance.mark('createMetadata:start');
|
265
|
+
let spinner;
|
266
|
+
const inProgressPlugins = new Set();
|
267
|
+
function updateSpinner() {
|
268
|
+
if (!spinner) {
|
269
|
+
return;
|
270
|
+
}
|
271
|
+
if (inProgressPlugins.size === 1) {
|
272
|
+
return `Creating project metadata with ${inProgressPlugins.keys()[0]}`;
|
273
|
+
}
|
274
|
+
else if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
275
|
+
return [
|
276
|
+
`Creating project metadata with ${inProgressPlugins.size} plugins`,
|
277
|
+
...Array.from(inProgressPlugins).map((p) => ` - ${p}`),
|
278
|
+
].join('\n');
|
279
|
+
}
|
280
|
+
else {
|
281
|
+
return `Creating project metadata with ${inProgressPlugins.size} plugins`;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
if (delayed_spinner_1.SHOULD_SHOW_SPINNERS) {
|
285
|
+
spinner = new delayed_spinner_1.DelayedSpinner(`Creating project metadata with ${plugins.length} plugins`);
|
286
|
+
}
|
235
287
|
const promises = plugins.map(async (plugin) => {
|
236
288
|
if (plugin.createMetadata) {
|
237
289
|
perf_hooks_1.performance.mark(`${plugin.name}:createMetadata - start`);
|
290
|
+
inProgressPlugins.add(plugin.name);
|
238
291
|
try {
|
239
292
|
const metadata = await plugin.createMetadata(graph, context);
|
240
293
|
results.push({ metadata, pluginName: plugin.name });
|
@@ -243,12 +296,15 @@ async function applyProjectMetadata(graph, plugins, context, sourceMap) {
|
|
243
296
|
errors.push(new error_types_1.CreateMetadataError(e, plugin.name));
|
244
297
|
}
|
245
298
|
finally {
|
299
|
+
inProgressPlugins.delete(plugin.name);
|
300
|
+
updateSpinner();
|
246
301
|
perf_hooks_1.performance.mark(`${plugin.name}:createMetadata - end`);
|
247
302
|
perf_hooks_1.performance.measure(`${plugin.name}:createMetadata`, `${plugin.name}:createMetadata - start`, `${plugin.name}:createMetadata - end`);
|
248
303
|
}
|
249
304
|
}
|
250
305
|
});
|
251
306
|
await Promise.all(promises);
|
307
|
+
spinner?.cleanup();
|
252
308
|
for (const { metadata: projectsMetadata, pluginName } of results) {
|
253
309
|
for (const project in projectsMetadata) {
|
254
310
|
const projectConfiguration = graph.nodes[project]?.data;
|
@@ -1,14 +1,15 @@
|
|
1
1
|
import { PluginConfiguration } from '../../config/nx-json';
|
2
|
-
import {
|
2
|
+
import { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, NxPluginV2, ProjectsMetadata } from './public-api';
|
3
3
|
import { ProjectGraph } from '../../config/project-graph';
|
4
|
+
import { RawProjectGraphDependency } from '../project-graph-builder';
|
4
5
|
export declare class LoadedNxPlugin {
|
5
6
|
readonly name: string;
|
6
7
|
readonly createNodes?: [
|
7
8
|
filePattern: string,
|
8
9
|
fn: (matchedFiles: string[], context: CreateNodesContextV2) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
|
9
10
|
];
|
10
|
-
readonly createDependencies?: (context: CreateDependenciesContext) =>
|
11
|
-
readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) =>
|
11
|
+
readonly createDependencies?: (context: CreateDependenciesContext) => Promise<RawProjectGraphDependency[]>;
|
12
|
+
readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) => Promise<ProjectsMetadata>;
|
12
13
|
readonly options?: unknown;
|
13
14
|
readonly include?: string[];
|
14
15
|
readonly exclude?: string[];
|
@@ -57,10 +57,10 @@ class LoadedNxPlugin {
|
|
57
57
|
};
|
58
58
|
}
|
59
59
|
if (plugin.createDependencies) {
|
60
|
-
this.createDependencies = (context) => plugin.createDependencies(this.options, context);
|
60
|
+
this.createDependencies = async (context) => plugin.createDependencies(this.options, context);
|
61
61
|
}
|
62
62
|
if (plugin.createMetadata) {
|
63
|
-
this.createMetadata = (graph, context) => plugin.createMetadata(graph, this.options, context);
|
63
|
+
this.createMetadata = async (graph, context) => plugin.createMetadata(graph, this.options, context);
|
64
64
|
}
|
65
65
|
}
|
66
66
|
}
|
@@ -68,7 +68,7 @@ export interface PluginCreateMetadataMessage {
|
|
68
68
|
export interface PluginCreateDependenciesResult {
|
69
69
|
type: 'createDependenciesResult';
|
70
70
|
payload: {
|
71
|
-
dependencies: ReturnType<LoadedNxPlugin['createDependencies']
|
71
|
+
dependencies: Awaited<ReturnType<LoadedNxPlugin['createDependencies']>>;
|
72
72
|
success: true;
|
73
73
|
tx: string;
|
74
74
|
} | {
|
@@ -80,7 +80,7 @@ export interface PluginCreateDependenciesResult {
|
|
80
80
|
export interface PluginCreateMetadataResult {
|
81
81
|
type: 'createMetadataResult';
|
82
82
|
payload: {
|
83
|
-
metadata: ReturnType<LoadedNxPlugin['createMetadata']
|
83
|
+
metadata: Awaited<ReturnType<LoadedNxPlugin['createMetadata']>>;
|
84
84
|
success: true;
|
85
85
|
tx: string;
|
86
86
|
} | {
|
@@ -20,6 +20,7 @@ const path_1 = require("path");
|
|
20
20
|
const perf_hooks_1 = require("perf_hooks");
|
21
21
|
const error_types_1 = require("../error-types");
|
22
22
|
const globs_1 = require("../../utils/globs");
|
23
|
+
const delayed_spinner_1 = require("../../utils/delayed-spinner");
|
23
24
|
function mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInformation,
|
24
25
|
// This function is used when reading project configuration
|
25
26
|
// in generators, where we don't want to do this.
|
@@ -224,6 +225,28 @@ function mergeMetadata(sourceMap, sourceInformation, baseSourceMapPath, metadata
|
|
224
225
|
async function createProjectConfigurations(root = workspace_root_1.workspaceRoot, nxJson, projectFiles, // making this parameter allows devkit to pick up newly created projects
|
225
226
|
plugins) {
|
226
227
|
perf_hooks_1.performance.mark('build-project-configs:start');
|
228
|
+
let spinner;
|
229
|
+
const inProgressPlugins = new Set();
|
230
|
+
function updateSpinner() {
|
231
|
+
if (!spinner) {
|
232
|
+
return;
|
233
|
+
}
|
234
|
+
if (inProgressPlugins.size === 1) {
|
235
|
+
return `Creating project graph nodes with ${inProgressPlugins.keys()[0]}`;
|
236
|
+
}
|
237
|
+
else if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
238
|
+
return [
|
239
|
+
`Creating project graph nodes with ${inProgressPlugins.size} plugins`,
|
240
|
+
...Array.from(inProgressPlugins).map((p) => ` - ${p}`),
|
241
|
+
].join('\n');
|
242
|
+
}
|
243
|
+
else {
|
244
|
+
return `Creating project graph nodes with ${inProgressPlugins.size} plugins`;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
if (delayed_spinner_1.SHOULD_SHOW_SPINNERS) {
|
248
|
+
spinner = new delayed_spinner_1.DelayedSpinner(`Creating project graph nodes with ${plugins.length} plugins`);
|
249
|
+
}
|
227
250
|
const results = [];
|
228
251
|
const errors = [];
|
229
252
|
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
@@ -233,10 +256,12 @@ plugins) {
|
|
233
256
|
continue;
|
234
257
|
}
|
235
258
|
const matchingConfigFiles = findMatchingConfigFiles(projectFiles, pattern, include, exclude);
|
259
|
+
inProgressPlugins.add(pluginName);
|
236
260
|
let r = createNodes(matchingConfigFiles, {
|
237
261
|
nxJsonConfiguration: nxJson,
|
238
262
|
workspaceRoot: root,
|
239
|
-
})
|
263
|
+
})
|
264
|
+
.catch((e) => {
|
240
265
|
const errorBodyLines = [
|
241
266
|
`An error occurred while processing files for the ${pluginName} plugin.`,
|
242
267
|
];
|
@@ -263,10 +288,15 @@ plugins) {
|
|
263
288
|
errors.push(error);
|
264
289
|
// The plugin didn't return partial results, so we return an empty array.
|
265
290
|
return error.partialResults.map((r) => [pluginName, r[0], r[1]]);
|
291
|
+
})
|
292
|
+
.finally(() => {
|
293
|
+
inProgressPlugins.delete(pluginName);
|
294
|
+
updateSpinner();
|
266
295
|
});
|
267
296
|
results.push(r);
|
268
297
|
}
|
269
298
|
return Promise.all(results).then((results) => {
|
299
|
+
spinner?.cleanup();
|
270
300
|
const { projectRootMap, externalNodes, rootMap, configurationSourceMaps } = mergeCreateNodesResults(results, nxJson, errors);
|
271
301
|
perf_hooks_1.performance.mark('build-project-configs:end');
|
272
302
|
perf_hooks_1.performance.measure('build-project-configs', 'build-project-configs:start', 'build-project-configs:end');
|
@@ -220,24 +220,46 @@ class ForkedProcessTaskRunner {
|
|
220
220
|
}
|
221
221
|
}
|
222
222
|
let outWithErr = [];
|
223
|
+
let exitCode;
|
224
|
+
let stdoutHasEnded = false;
|
225
|
+
let stderrHasEnded = false;
|
226
|
+
let processHasExited = false;
|
227
|
+
const handleProcessEnd = () => {
|
228
|
+
// ensure process has exited and both stdout and stderr have ended before we pass along the logs
|
229
|
+
// if we only wait for the process to exit, we might miss some logs as stdout and stderr might still be streaming
|
230
|
+
if (stdoutHasEnded && stderrHasEnded && processHasExited) {
|
231
|
+
// we didn't print any output as we were running the command
|
232
|
+
// print all the collected output|
|
233
|
+
const terminalOutput = outWithErr.join('');
|
234
|
+
const code = exitCode;
|
235
|
+
if (!streamOutput) {
|
236
|
+
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
237
|
+
}
|
238
|
+
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
239
|
+
res({ code, terminalOutput });
|
240
|
+
}
|
241
|
+
};
|
223
242
|
p.stdout.on('data', (chunk) => {
|
224
243
|
outWithErr.push(chunk.toString());
|
225
244
|
});
|
245
|
+
p.stdout.on('end', () => {
|
246
|
+
stdoutHasEnded = true;
|
247
|
+
handleProcessEnd();
|
248
|
+
});
|
226
249
|
p.stderr.on('data', (chunk) => {
|
227
250
|
outWithErr.push(chunk.toString());
|
228
251
|
});
|
252
|
+
p.stderr.on('end', () => {
|
253
|
+
stderrHasEnded = true;
|
254
|
+
handleProcessEnd();
|
255
|
+
});
|
229
256
|
p.on('exit', (code, signal) => {
|
230
257
|
this.processes.delete(p);
|
231
258
|
if (code === null)
|
232
259
|
code = (0, exit_codes_1.signalToCode)(signal);
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
if (!streamOutput) {
|
237
|
-
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
238
|
-
}
|
239
|
-
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
240
|
-
res({ code, terminalOutput });
|
260
|
+
exitCode = code;
|
261
|
+
processHasExited = true;
|
262
|
+
handleProcessEnd();
|
241
263
|
});
|
242
264
|
}
|
243
265
|
catch (e) {
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import * as ora from 'ora';
|
2
|
+
/**
|
3
|
+
* A class that allows to delay the creation of a spinner, as well
|
4
|
+
* as schedule updates to the message of the spinner. Useful for
|
5
|
+
* scenarios where one wants to only show a spinner if an operation
|
6
|
+
* takes longer than a certain amount of time.
|
7
|
+
*/
|
8
|
+
export declare class DelayedSpinner {
|
9
|
+
spinner: ora.Ora;
|
10
|
+
timeouts: NodeJS.Timeout[];
|
11
|
+
initial: number;
|
12
|
+
/**
|
13
|
+
* Constructs a new {@link DelayedSpinner} instance.
|
14
|
+
*
|
15
|
+
* @param message The message to display in the spinner
|
16
|
+
* @param ms The number of milliseconds to wait before creating the spinner
|
17
|
+
*/
|
18
|
+
constructor(message: string, ms?: number);
|
19
|
+
/**
|
20
|
+
* Sets the message to display in the spinner.
|
21
|
+
*
|
22
|
+
* @param message The message to display in the spinner
|
23
|
+
* @returns The {@link DelayedSpinner} instance
|
24
|
+
*/
|
25
|
+
setMessage(message: string): this;
|
26
|
+
/**
|
27
|
+
* Schedules an update to the message of the spinner. Useful for
|
28
|
+
* changing the message after a certain amount of time has passed.
|
29
|
+
*
|
30
|
+
* @param message The message to display in the spinner
|
31
|
+
* @param delay How long to wait before updating the message
|
32
|
+
* @returns The {@link DelayedSpinner} instance
|
33
|
+
*/
|
34
|
+
scheduleMessageUpdate(message: string, delay: number): this;
|
35
|
+
/**
|
36
|
+
* Stops the spinner and cleans up any scheduled timeouts.
|
37
|
+
*/
|
38
|
+
cleanup(): void;
|
39
|
+
}
|
40
|
+
export declare const SHOULD_SHOW_SPINNERS: boolean;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SHOULD_SHOW_SPINNERS = exports.DelayedSpinner = void 0;
|
4
|
+
const ora = require("ora");
|
5
|
+
/**
|
6
|
+
* A class that allows to delay the creation of a spinner, as well
|
7
|
+
* as schedule updates to the message of the spinner. Useful for
|
8
|
+
* scenarios where one wants to only show a spinner if an operation
|
9
|
+
* takes longer than a certain amount of time.
|
10
|
+
*/
|
11
|
+
class DelayedSpinner {
|
12
|
+
/**
|
13
|
+
* Constructs a new {@link DelayedSpinner} instance.
|
14
|
+
*
|
15
|
+
* @param message The message to display in the spinner
|
16
|
+
* @param ms The number of milliseconds to wait before creating the spinner
|
17
|
+
*/
|
18
|
+
constructor(message, ms = 500) {
|
19
|
+
this.timeouts = [];
|
20
|
+
this.initial = Date.now();
|
21
|
+
this.timeouts.push(setTimeout(() => {
|
22
|
+
this.spinner = ora(message);
|
23
|
+
}, ms).unref());
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* Sets the message to display in the spinner.
|
27
|
+
*
|
28
|
+
* @param message The message to display in the spinner
|
29
|
+
* @returns The {@link DelayedSpinner} instance
|
30
|
+
*/
|
31
|
+
setMessage(message) {
|
32
|
+
this.spinner.text = message;
|
33
|
+
return this;
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* Schedules an update to the message of the spinner. Useful for
|
37
|
+
* changing the message after a certain amount of time has passed.
|
38
|
+
*
|
39
|
+
* @param message The message to display in the spinner
|
40
|
+
* @param delay How long to wait before updating the message
|
41
|
+
* @returns The {@link DelayedSpinner} instance
|
42
|
+
*/
|
43
|
+
scheduleMessageUpdate(message, delay) {
|
44
|
+
this.timeouts.push(setTimeout(() => {
|
45
|
+
this.spinner.text = message;
|
46
|
+
}, delay).unref());
|
47
|
+
return this;
|
48
|
+
}
|
49
|
+
/**
|
50
|
+
* Stops the spinner and cleans up any scheduled timeouts.
|
51
|
+
*/
|
52
|
+
cleanup() {
|
53
|
+
this.spinner?.stop();
|
54
|
+
this.timeouts.forEach((t) => clearTimeout(t));
|
55
|
+
}
|
56
|
+
}
|
57
|
+
exports.DelayedSpinner = DelayedSpinner;
|
58
|
+
exports.SHOULD_SHOW_SPINNERS = process.stdout.isTTY;
|
@@ -1,3 +0,0 @@
|
|
1
|
-
import { PackageManager } from '../../../utils/package-manager';
|
2
|
-
export declare function getPackagesInPackageManagerWorkspace(packageManager: PackageManager): Promise<Set<string>>;
|
3
|
-
export declare function needsInstall(packageManager: PackageManager, originalPackagesInPackageManagerWorkspaces: Set<string>): Promise<boolean>;
|
@@ -1,31 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.getPackagesInPackageManagerWorkspace = getPackagesInPackageManagerWorkspace;
|
4
|
-
exports.needsInstall = needsInstall;
|
5
|
-
const package_manager_1 = require("../../../utils/package-manager");
|
6
|
-
const workspace_root_1 = require("../../../utils/workspace-root");
|
7
|
-
const package_json_1 = require("../../../plugins/package-json");
|
8
|
-
const workspace_context_1 = require("../../../utils/workspace-context");
|
9
|
-
async function getPackagesInPackageManagerWorkspace(packageManager) {
|
10
|
-
if (!(0, package_manager_1.isWorkspacesEnabled)(packageManager, workspace_root_1.workspaceRoot)) {
|
11
|
-
return new Set();
|
12
|
-
}
|
13
|
-
const patterns = (0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(workspace_root_1.workspaceRoot);
|
14
|
-
return new Set(await (0, workspace_context_1.globWithWorkspaceContext)(workspace_root_1.workspaceRoot, patterns));
|
15
|
-
}
|
16
|
-
async function needsInstall(packageManager, originalPackagesInPackageManagerWorkspaces) {
|
17
|
-
if (!(0, package_manager_1.isWorkspacesEnabled)(packageManager, workspace_root_1.workspaceRoot)) {
|
18
|
-
return false;
|
19
|
-
}
|
20
|
-
const updatedPackagesInPackageManagerWorkspaces = await getPackagesInPackageManagerWorkspace(packageManager);
|
21
|
-
if (updatedPackagesInPackageManagerWorkspaces.size !==
|
22
|
-
originalPackagesInPackageManagerWorkspaces.size) {
|
23
|
-
return true;
|
24
|
-
}
|
25
|
-
for (const pkg of updatedPackagesInPackageManagerWorkspaces) {
|
26
|
-
if (!originalPackagesInPackageManagerWorkspaces.has(pkg)) {
|
27
|
-
return true;
|
28
|
-
}
|
29
|
-
}
|
30
|
-
return false;
|
31
|
-
}
|