@angular/cli 18.1.0-next.2 → 18.1.0-rc.0
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/lib/cli/index.js +5 -4
- package/package.json +18 -18
- package/src/command-builder/architect-base-command-module.js +1 -1
- package/src/command-builder/architect-command-module.js +158 -124
- package/src/command-builder/command-module.js +225 -196
- package/src/command-builder/schematics-command-module.js +308 -284
- package/src/commands/add/cli.js +193 -123
- package/src/commands/new/cli.js +1 -1
- package/src/commands/update/cli.js +62 -31
- package/src/utilities/color.d.ts +2 -3
- package/src/utilities/color.js +15 -51
- package/src/utilities/memoize.d.ts +1 -1
- package/src/utilities/memoize.js +14 -19
- package/src/utilities/package-manager.js +265 -245
- package/src/utilities/tty.d.ts +1 -1
- package/src/utilities/tty.js +2 -2
- package/src/utilities/version.js +1 -1
- package/src/utilities/spinner.d.ts +0 -20
- package/src/utilities/spinner.js +0 -55
package/src/commands/add/cli.js
CHANGED
|
@@ -6,24 +6,48 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
26
|
+
if (mod && mod.__esModule) return mod;
|
|
27
|
+
var result = {};
|
|
28
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
29
|
+
__setModuleDefault(result, mod);
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
9
32
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
33
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
34
|
};
|
|
12
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
36
|
const tools_1 = require("@angular-devkit/schematics/tools");
|
|
37
|
+
const listr2_1 = require("listr2");
|
|
14
38
|
const module_1 = require("module");
|
|
39
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
40
|
const npm_package_arg_1 = __importDefault(require("npm-package-arg"));
|
|
16
41
|
const path_1 = require("path");
|
|
17
42
|
const semver_1 = require("semver");
|
|
18
43
|
const workspace_schema_1 = require("../../../lib/config/workspace-schema");
|
|
19
44
|
const schematics_command_module_1 = require("../../command-builder/schematics-command-module");
|
|
20
|
-
const color_1 = require("../../utilities/color");
|
|
21
45
|
const error_1 = require("../../utilities/error");
|
|
22
46
|
const package_metadata_1 = require("../../utilities/package-metadata");
|
|
23
|
-
const prompt_1 = require("../../utilities/prompt");
|
|
24
|
-
const spinner_1 = require("../../utilities/spinner");
|
|
25
47
|
const tty_1 = require("../../utilities/tty");
|
|
26
48
|
const version_1 = require("../../utilities/version");
|
|
49
|
+
class CommandError extends Error {
|
|
50
|
+
}
|
|
27
51
|
/**
|
|
28
52
|
* The set of packages that should have certain versions excluded from consideration
|
|
29
53
|
* when attempting to find a compatible version for a package.
|
|
@@ -66,7 +90,7 @@ class AddCommandModule extends schematics_command_module_1.SchematicsCommandModu
|
|
|
66
90
|
// `ng add @angular/localize -- --package-options`.
|
|
67
91
|
.strict(false);
|
|
68
92
|
const collectionName = await this.getCollectionName();
|
|
69
|
-
const workflow =
|
|
93
|
+
const workflow = this.getOrCreateWorkflowForBuilder(collectionName);
|
|
70
94
|
try {
|
|
71
95
|
const collection = workflow.engine.createCollection(collectionName);
|
|
72
96
|
const options = await this.getSchematicOptions(collection, this.schematicName, workflow);
|
|
@@ -102,135 +126,181 @@ class AddCommandModule extends schematics_command_module_1.SchematicsCommandModu
|
|
|
102
126
|
return this.executeSchematic({ ...options, collection: packageIdentifier.name });
|
|
103
127
|
}
|
|
104
128
|
}
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// Adjust the version based on name and peer dependencies
|
|
134
|
-
if (latestManifest?.peerDependencies &&
|
|
135
|
-
Object.keys(latestManifest.peerDependencies).length === 0) {
|
|
136
|
-
spinner.succeed(`Found compatible package version: ${color_1.colors.grey(packageIdentifier.toString())}.`);
|
|
137
|
-
}
|
|
138
|
-
else if (!latestManifest || (await this.hasMismatchedPeer(latestManifest))) {
|
|
139
|
-
// 'latest' is invalid so search for most recent matching package
|
|
140
|
-
// Allow prelease versions if the CLI itself is a prerelease
|
|
141
|
-
const allowPrereleases = (0, semver_1.prerelease)(version_1.VERSION.full);
|
|
142
|
-
const versionExclusions = packageVersionExclusions[packageMetadata.name];
|
|
143
|
-
const versionManifests = Object.values(packageMetadata.versions).filter((value) => {
|
|
144
|
-
// Prerelease versions are not stable and should not be considered by default
|
|
145
|
-
if (!allowPrereleases && (0, semver_1.prerelease)(value.version)) {
|
|
146
|
-
return false;
|
|
129
|
+
const taskContext = {
|
|
130
|
+
packageIdentifier,
|
|
131
|
+
executeSchematic: this.executeSchematic.bind(this),
|
|
132
|
+
hasMismatchedPeer: this.hasMismatchedPeer.bind(this),
|
|
133
|
+
};
|
|
134
|
+
const tasks = new listr2_1.Listr([
|
|
135
|
+
{
|
|
136
|
+
title: 'Determining Package Manager',
|
|
137
|
+
task(context, task) {
|
|
138
|
+
context.usingYarn = packageManager.name === workspace_schema_1.PackageManager.Yarn;
|
|
139
|
+
task.output = `Using package manager: ${listr2_1.color.dim(packageManager.name)}`;
|
|
140
|
+
},
|
|
141
|
+
rendererOptions: { persistentOutput: true },
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
title: 'Searching for compatible package version',
|
|
145
|
+
enabled: packageIdentifier.type === 'range' && packageIdentifier.rawSpec === '*',
|
|
146
|
+
async task(context, task) {
|
|
147
|
+
(0, node_assert_1.default)(context.packageIdentifier.name, 'Registry package identifiers should always have a name.');
|
|
148
|
+
// only package name provided; search for viable version
|
|
149
|
+
// plus special cases for packages that did not have peer deps setup
|
|
150
|
+
let packageMetadata;
|
|
151
|
+
try {
|
|
152
|
+
packageMetadata = await (0, package_metadata_1.fetchPackageMetadata)(context.packageIdentifier.name, logger, {
|
|
153
|
+
registry,
|
|
154
|
+
usingYarn: context.usingYarn,
|
|
155
|
+
verbose,
|
|
156
|
+
});
|
|
147
157
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
158
|
+
catch (e) {
|
|
159
|
+
(0, error_1.assertIsError)(e);
|
|
160
|
+
throw new CommandError(`Unable to load package information from registry: ${e.message}`);
|
|
151
161
|
}
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
// Start with the version tagged as `latest` if it exists
|
|
163
|
+
const latestManifest = packageMetadata.tags['latest'];
|
|
164
|
+
if (latestManifest) {
|
|
165
|
+
context.packageIdentifier = npm_package_arg_1.default.resolve(latestManifest.name, latestManifest.version);
|
|
156
166
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
let newIdentifier;
|
|
162
|
-
for (const versionManifest of versionManifests) {
|
|
163
|
-
if (!(await this.hasMismatchedPeer(versionManifest))) {
|
|
164
|
-
newIdentifier = npm_package_arg_1.default.resolve(versionManifest.name, versionManifest.version);
|
|
165
|
-
break;
|
|
167
|
+
// Adjust the version based on name and peer dependencies
|
|
168
|
+
if (latestManifest?.peerDependencies &&
|
|
169
|
+
Object.keys(latestManifest.peerDependencies).length === 0) {
|
|
170
|
+
task.output = `Found compatible package version: ${listr2_1.color.blue(latestManifest.version)}.`;
|
|
166
171
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
172
|
+
else if (!latestManifest || (await context.hasMismatchedPeer(latestManifest))) {
|
|
173
|
+
// 'latest' is invalid so search for most recent matching package
|
|
174
|
+
// Allow prelease versions if the CLI itself is a prerelease
|
|
175
|
+
const allowPrereleases = (0, semver_1.prerelease)(version_1.VERSION.full);
|
|
176
|
+
const versionExclusions = packageVersionExclusions[packageMetadata.name];
|
|
177
|
+
const versionManifests = Object.values(packageMetadata.versions).filter((value) => {
|
|
178
|
+
// Prerelease versions are not stable and should not be considered by default
|
|
179
|
+
if (!allowPrereleases && (0, semver_1.prerelease)(value.version)) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
// Deprecated versions should not be used or considered
|
|
183
|
+
if (value.deprecated) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
// Excluded package versions should not be considered
|
|
187
|
+
if (versionExclusions &&
|
|
188
|
+
(0, semver_1.satisfies)(value.version, versionExclusions, { includePrerelease: true })) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
return true;
|
|
192
|
+
});
|
|
193
|
+
// Sort in reverse SemVer order so that the newest compatible version is chosen
|
|
194
|
+
versionManifests.sort((a, b) => (0, semver_1.compare)(b.version, a.version, true));
|
|
195
|
+
let found = false;
|
|
196
|
+
for (const versionManifest of versionManifests) {
|
|
197
|
+
const mismatch = await context.hasMismatchedPeer(versionManifest);
|
|
198
|
+
if (mismatch) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
context.packageIdentifier = npm_package_arg_1.default.resolve(versionManifest.name, versionManifest.version);
|
|
202
|
+
found = true;
|
|
203
|
+
}
|
|
204
|
+
if (!found) {
|
|
205
|
+
task.output = "Unable to find compatible package. Using 'latest' tag.";
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
task.output = `Found compatible package version: ${listr2_1.color.blue(context.packageIdentifier.toString())}.`;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
task.output = `Found compatible package version: ${listr2_1.color.blue(context.packageIdentifier.toString())}.`;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
rendererOptions: { persistentOutput: true },
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
title: 'Loading package information from registry',
|
|
219
|
+
async task(context, task) {
|
|
220
|
+
let manifest;
|
|
221
|
+
try {
|
|
222
|
+
manifest = await (0, package_metadata_1.fetchPackageManifest)(context.packageIdentifier.toString(), logger, {
|
|
223
|
+
registry,
|
|
224
|
+
verbose,
|
|
225
|
+
usingYarn: context.usingYarn,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
(0, error_1.assertIsError)(e);
|
|
230
|
+
throw new CommandError(`Unable to fetch package information for '${context.packageIdentifier}': ${e.message}`);
|
|
231
|
+
}
|
|
232
|
+
context.savePackage = manifest['ng-add']?.save;
|
|
233
|
+
context.collectionName = manifest.name;
|
|
234
|
+
if (await context.hasMismatchedPeer(manifest)) {
|
|
235
|
+
task.output = listr2_1.color.yellow(listr2_1.figures.warning +
|
|
236
|
+
' Package has unmet peer dependencies. Adding the package may not succeed.');
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
rendererOptions: { persistentOutput: true },
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
title: 'Confirming installation',
|
|
243
|
+
enabled: !skipConfirmation,
|
|
244
|
+
async task(context, task) {
|
|
245
|
+
if (!(0, tty_1.isTTY)()) {
|
|
246
|
+
task.output =
|
|
247
|
+
`'--skip-confirmation' can be used to bypass installation confirmation. ` +
|
|
248
|
+
`Ensure package name is correct prior to '--skip-confirmation' option usage.`;
|
|
249
|
+
throw new CommandError('No terminal detected');
|
|
250
|
+
}
|
|
251
|
+
const { ListrInquirerPromptAdapter } = await Promise.resolve().then(() => __importStar(require('@listr2/prompt-adapter-inquirer')));
|
|
252
|
+
const { confirm } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
|
|
253
|
+
const shouldProceed = await task.prompt(ListrInquirerPromptAdapter).run(confirm, {
|
|
254
|
+
message: `The package ${listr2_1.color.blue(context.packageIdentifier.toString())} will be installed and executed.\n` +
|
|
255
|
+
'Would you like to proceed?',
|
|
256
|
+
default: true,
|
|
257
|
+
theme: { prefix: '' },
|
|
258
|
+
});
|
|
259
|
+
if (!shouldProceed) {
|
|
260
|
+
throw new CommandError('Command aborted');
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
rendererOptions: { persistentOutput: true },
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
async task(context, task) {
|
|
267
|
+
// Only show if installation will actually occur
|
|
268
|
+
task.title = 'Installing package';
|
|
269
|
+
if (context.savePackage === false) {
|
|
270
|
+
task.title += ' in temporary location';
|
|
271
|
+
// Temporary packages are located in a different directory
|
|
272
|
+
// Hence we need to resolve them using the temp path
|
|
273
|
+
const { success, tempNodeModules } = await packageManager.installTemp(context.packageIdentifier.toString(), registry ? [`--registry="${registry}"`] : undefined);
|
|
274
|
+
const tempRequire = (0, module_1.createRequire)(tempNodeModules + '/');
|
|
275
|
+
(0, node_assert_1.default)(context.collectionName, 'Collection name should always be available');
|
|
276
|
+
const resolvedCollectionPath = tempRequire.resolve((0, path_1.join)(context.collectionName, 'package.json'));
|
|
277
|
+
if (!success) {
|
|
278
|
+
throw new CommandError('Unable to install package');
|
|
279
|
+
}
|
|
280
|
+
context.collectionName = (0, path_1.dirname)(resolvedCollectionPath);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const success = await packageManager.install(context.packageIdentifier.toString(), context.savePackage, registry ? [`--registry="${registry}"`] : undefined, undefined);
|
|
284
|
+
if (!success) {
|
|
285
|
+
throw new CommandError('Unable to install package');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
rendererOptions: { bottomBar: Infinity },
|
|
290
|
+
},
|
|
291
|
+
// TODO: Rework schematic execution as a task and insert here
|
|
292
|
+
]);
|
|
182
293
|
try {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
verbose,
|
|
187
|
-
usingYarn,
|
|
188
|
-
});
|
|
189
|
-
savePackage = manifest['ng-add']?.save;
|
|
190
|
-
collectionName = manifest.name;
|
|
191
|
-
if (await this.hasMismatchedPeer(manifest)) {
|
|
192
|
-
spinner.warn('Package has unmet peer dependencies. Adding the package may not succeed.');
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
spinner.succeed(`Package information loaded.`);
|
|
196
|
-
}
|
|
294
|
+
const result = await tasks.run(taskContext);
|
|
295
|
+
(0, node_assert_1.default)(result.collectionName, 'Collection name should always be available');
|
|
296
|
+
return this.executeSchematic({ ...options, collection: result.collectionName });
|
|
197
297
|
}
|
|
198
298
|
catch (e) {
|
|
199
|
-
|
|
200
|
-
spinner.fail(`Unable to fetch package information for '${packageIdentifier}': ${e.message}`);
|
|
201
|
-
return 1;
|
|
202
|
-
}
|
|
203
|
-
if (!skipConfirmation) {
|
|
204
|
-
const confirmationResponse = await (0, prompt_1.askConfirmation)(`\nThe package ${color_1.colors.blue(packageIdentifier.raw)} will be installed and executed.\n` +
|
|
205
|
-
'Would you like to proceed?', true, false);
|
|
206
|
-
if (!confirmationResponse) {
|
|
207
|
-
if (!(0, tty_1.isTTY)()) {
|
|
208
|
-
logger.error('No terminal detected. ' +
|
|
209
|
-
`'--skip-confirmation' can be used to bypass installation confirmation. ` +
|
|
210
|
-
`Ensure package name is correct prior to '--skip-confirmation' option usage.`);
|
|
211
|
-
}
|
|
212
|
-
logger.error('Command aborted.');
|
|
213
|
-
return 1;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (savePackage === false) {
|
|
217
|
-
// Temporary packages are located in a different directory
|
|
218
|
-
// Hence we need to resolve them using the temp path
|
|
219
|
-
const { success, tempNodeModules } = await packageManager.installTemp(packageIdentifier.raw, registry ? [`--registry="${registry}"`] : undefined);
|
|
220
|
-
const tempRequire = (0, module_1.createRequire)(tempNodeModules + '/');
|
|
221
|
-
const resolvedCollectionPath = tempRequire.resolve((0, path_1.join)(collectionName, 'package.json'));
|
|
222
|
-
if (!success) {
|
|
223
|
-
return 1;
|
|
224
|
-
}
|
|
225
|
-
collectionName = (0, path_1.dirname)(resolvedCollectionPath);
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
const success = await packageManager.install(packageIdentifier.raw, savePackage, registry ? [`--registry="${registry}"`] : undefined);
|
|
229
|
-
if (!success) {
|
|
299
|
+
if (e instanceof CommandError) {
|
|
230
300
|
return 1;
|
|
231
301
|
}
|
|
302
|
+
throw e;
|
|
232
303
|
}
|
|
233
|
-
return this.executeSchematic({ ...options, collection: collectionName });
|
|
234
304
|
}
|
|
235
305
|
async isProjectVersionValid(packageIdentifier) {
|
|
236
306
|
if (!packageIdentifier.name) {
|
package/src/commands/new/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ class NewCommandModule extends schematics_command_module_1.SchematicsCommandModu
|
|
|
30
30
|
const collectionName = typeof collectionNameFromArgs === 'string'
|
|
31
31
|
? collectionNameFromArgs
|
|
32
32
|
: await this.getCollectionFromConfig();
|
|
33
|
-
const workflow =
|
|
33
|
+
const workflow = this.getOrCreateWorkflowForBuilder(collectionName);
|
|
34
34
|
const collection = workflow.engine.createCollection(collectionName);
|
|
35
35
|
const options = await this.getSchematicOptions(collection, this.schematicName, workflow);
|
|
36
36
|
return this.addSchemaOptionsToCommand(localYargs, options);
|
|
@@ -35,9 +35,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
37
37
|
const tools_1 = require("@angular-devkit/schematics/tools");
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
38
|
+
const listr2_1 = require("listr2");
|
|
39
|
+
const node_child_process_1 = require("node:child_process");
|
|
40
|
+
const node_fs_1 = require("node:fs");
|
|
41
|
+
const node_module_1 = require("node:module");
|
|
41
42
|
const npm_package_arg_1 = __importDefault(require("npm-package-arg"));
|
|
42
43
|
const npm_pick_manifest_1 = __importDefault(require("npm-pick-manifest"));
|
|
43
44
|
const path = __importStar(require("path"));
|
|
@@ -56,6 +57,8 @@ const package_tree_1 = require("../../utilities/package-tree");
|
|
|
56
57
|
const prompt_1 = require("../../utilities/prompt");
|
|
57
58
|
const tty_1 = require("../../utilities/tty");
|
|
58
59
|
const version_1 = require("../../utilities/version");
|
|
60
|
+
class CommandError extends Error {
|
|
61
|
+
}
|
|
59
62
|
const ANGULAR_PACKAGES_REGEXP = /^@(?:angular|nguniversal)\//;
|
|
60
63
|
const UPDATE_SCHEMATIC_COLLECTION = path.join(__dirname, 'schematic/collection.json');
|
|
61
64
|
class UpdateCommandModule extends command_module_1.CommandModule {
|
|
@@ -188,7 +191,7 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
188
191
|
return 1;
|
|
189
192
|
}
|
|
190
193
|
}
|
|
191
|
-
logger.info(`Using package manager: ${color_1.colors.
|
|
194
|
+
logger.info(`Using package manager: ${color_1.colors.gray(packageManager.name)}`);
|
|
192
195
|
logger.info('Collecting installed dependencies...');
|
|
193
196
|
const rootDependencies = await (0, package_tree_1.getProjectDependencies)(this.context.root);
|
|
194
197
|
logger.info(`Found ${rootDependencies.size} dependencies.`);
|
|
@@ -233,12 +236,12 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
233
236
|
}
|
|
234
237
|
catch (e) {
|
|
235
238
|
if (e instanceof schematics_1.UnsuccessfulWorkflowExecution) {
|
|
236
|
-
logger.error(`${color_1.
|
|
239
|
+
logger.error(`${color_1.figures.cross} Migration failed. See above for further details.\n`);
|
|
237
240
|
}
|
|
238
241
|
else {
|
|
239
242
|
(0, error_1.assertIsError)(e);
|
|
240
243
|
const logPath = (0, log_file_1.writeErrorToLogFile)(e);
|
|
241
|
-
logger.fatal(`${color_1.
|
|
244
|
+
logger.fatal(`${color_1.figures.cross} Migration failed: ${e.message}\n` +
|
|
242
245
|
` See "${logPath}" for further details.\n`);
|
|
243
246
|
}
|
|
244
247
|
return { success: false, files: workflowSubscription.files };
|
|
@@ -308,7 +311,7 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
308
311
|
const { logger } = this.context;
|
|
309
312
|
for (const migration of migrations) {
|
|
310
313
|
const { title, description } = getMigrationTitleAndDescription(migration);
|
|
311
|
-
logger.info(color_1.colors.cyan(color_1.
|
|
314
|
+
logger.info(color_1.colors.cyan(color_1.figures.pointer) + ' ' + color_1.colors.bold(title));
|
|
312
315
|
if (description) {
|
|
313
316
|
logger.info(' ' + description);
|
|
314
317
|
}
|
|
@@ -390,14 +393,14 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
390
393
|
}
|
|
391
394
|
// Check if it is a package-local location
|
|
392
395
|
const localMigrations = path.join(packagePath, migrations);
|
|
393
|
-
if ((0,
|
|
396
|
+
if ((0, node_fs_1.existsSync)(localMigrations)) {
|
|
394
397
|
migrations = localMigrations;
|
|
395
398
|
}
|
|
396
399
|
else {
|
|
397
400
|
// Try to resolve from package location.
|
|
398
401
|
// This avoids issues with package hoisting.
|
|
399
402
|
try {
|
|
400
|
-
const packageRequire = (0,
|
|
403
|
+
const packageRequire = (0, node_module_1.createRequire)(packagePath + '/');
|
|
401
404
|
migrations = packageRequire.resolve(migrations, { paths: this.resolvePaths });
|
|
402
405
|
}
|
|
403
406
|
catch (e) {
|
|
@@ -540,17 +543,45 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
540
543
|
packages: packagesToUpdate,
|
|
541
544
|
});
|
|
542
545
|
if (success) {
|
|
546
|
+
const { root: commandRoot, packageManager } = this.context;
|
|
547
|
+
const installArgs = this.packageManagerForce(options.verbose) ? ['--force'] : [];
|
|
548
|
+
const tasks = new listr2_1.Listr([
|
|
549
|
+
{
|
|
550
|
+
title: 'Cleaning node modules directory',
|
|
551
|
+
async task(_, task) {
|
|
552
|
+
try {
|
|
553
|
+
await node_fs_1.promises.rm(path.join(commandRoot, 'node_modules'), {
|
|
554
|
+
force: true,
|
|
555
|
+
recursive: true,
|
|
556
|
+
maxRetries: 3,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
catch (e) {
|
|
560
|
+
(0, error_1.assertIsError)(e);
|
|
561
|
+
if (e.code === 'ENOENT') {
|
|
562
|
+
task.skip('Cleaning not required. Node modules directory not found.');
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
title: 'Installing packages',
|
|
569
|
+
async task() {
|
|
570
|
+
const installationSuccess = await packageManager.installAll(installArgs, commandRoot);
|
|
571
|
+
if (!installationSuccess) {
|
|
572
|
+
throw new CommandError('Unable to install packages');
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
]);
|
|
543
577
|
try {
|
|
544
|
-
await
|
|
545
|
-
force: true,
|
|
546
|
-
recursive: true,
|
|
547
|
-
maxRetries: 3,
|
|
548
|
-
});
|
|
578
|
+
await tasks.run();
|
|
549
579
|
}
|
|
550
|
-
catch {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
580
|
+
catch (e) {
|
|
581
|
+
if (e instanceof CommandError) {
|
|
582
|
+
return 1;
|
|
583
|
+
}
|
|
584
|
+
throw e;
|
|
554
585
|
}
|
|
555
586
|
}
|
|
556
587
|
if (success && options.createCommits) {
|
|
@@ -562,7 +593,7 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
562
593
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
563
594
|
const migrations = global.externalMigrations;
|
|
564
595
|
if (success && migrations) {
|
|
565
|
-
const rootRequire = (0,
|
|
596
|
+
const rootRequire = (0, node_module_1.createRequire)(this.context.root + '/');
|
|
566
597
|
for (const migration of migrations) {
|
|
567
598
|
// Resolve the package from the workspace root, as otherwise it will be resolved from the temp
|
|
568
599
|
// installed CLI version.
|
|
@@ -600,14 +631,14 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
600
631
|
let migrations;
|
|
601
632
|
// Check if it is a package-local location
|
|
602
633
|
const localMigrations = path.join(packagePath, migration.collection);
|
|
603
|
-
if ((0,
|
|
634
|
+
if ((0, node_fs_1.existsSync)(localMigrations)) {
|
|
604
635
|
migrations = localMigrations;
|
|
605
636
|
}
|
|
606
637
|
else {
|
|
607
638
|
// Try to resolve from package location.
|
|
608
639
|
// This avoids issues with package hoisting.
|
|
609
640
|
try {
|
|
610
|
-
const packageRequire = (0,
|
|
641
|
+
const packageRequire = (0, node_module_1.createRequire)(packagePath + '/');
|
|
611
642
|
migrations = packageRequire.resolve(migration.collection);
|
|
612
643
|
}
|
|
613
644
|
catch (e) {
|
|
@@ -672,11 +703,11 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
672
703
|
}
|
|
673
704
|
checkCleanGit() {
|
|
674
705
|
try {
|
|
675
|
-
const topLevel = (0,
|
|
706
|
+
const topLevel = (0, node_child_process_1.execSync)('git rev-parse --show-toplevel', {
|
|
676
707
|
encoding: 'utf8',
|
|
677
708
|
stdio: 'pipe',
|
|
678
709
|
});
|
|
679
|
-
const result = (0,
|
|
710
|
+
const result = (0, node_child_process_1.execSync)('git status --porcelain', { encoding: 'utf8', stdio: 'pipe' });
|
|
680
711
|
if (result.trim().length === 0) {
|
|
681
712
|
return true;
|
|
682
713
|
}
|
|
@@ -736,8 +767,8 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
736
767
|
const packageJsonPath = (0, path_1.join)(pkgLocation, 'package.json');
|
|
737
768
|
// Get a binary location for this package
|
|
738
769
|
let binPath;
|
|
739
|
-
if ((0,
|
|
740
|
-
const content = await
|
|
770
|
+
if ((0, node_fs_1.existsSync)(packageJsonPath)) {
|
|
771
|
+
const content = await node_fs_1.promises.readFile(packageJsonPath, 'utf-8');
|
|
741
772
|
if (content) {
|
|
742
773
|
const { bin = {} } = JSON.parse(content);
|
|
743
774
|
const binKeys = Object.keys(bin);
|
|
@@ -749,7 +780,7 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
749
780
|
if (!binPath) {
|
|
750
781
|
throw new Error(`Cannot locate bin for temporary package: ${packageNameNoVersion}.`);
|
|
751
782
|
}
|
|
752
|
-
const { status, error } = (0,
|
|
783
|
+
const { status, error } = (0, node_child_process_1.spawnSync)(process.execPath, [binPath, ...args], {
|
|
753
784
|
stdio: 'inherit',
|
|
754
785
|
env: {
|
|
755
786
|
...process.env,
|
|
@@ -789,7 +820,7 @@ class UpdateCommandModule extends command_module_1.CommandModule {
|
|
|
789
820
|
if (!(0, tty_1.isTTY)()) {
|
|
790
821
|
for (const migration of optionalMigrations) {
|
|
791
822
|
const { title } = getMigrationTitleAndDescription(migration);
|
|
792
|
-
logger.info(color_1.colors.cyan(color_1.
|
|
823
|
+
logger.info(color_1.colors.cyan(color_1.figures.pointer) + ' ' + color_1.colors.bold(title));
|
|
793
824
|
logger.info(color_1.colors.gray(` ng update ${packageName} --name ${migration.name}`));
|
|
794
825
|
logger.info(''); // Extra trailing newline.
|
|
795
826
|
}
|
|
@@ -815,7 +846,7 @@ exports.default = UpdateCommandModule;
|
|
|
815
846
|
function hasChangesToCommit() {
|
|
816
847
|
// List all modified files not covered by .gitignore.
|
|
817
848
|
// If any files are returned, then there must be something to commit.
|
|
818
|
-
return (0,
|
|
849
|
+
return (0, node_child_process_1.execSync)('git ls-files -m -d -o --exclude-standard').toString() !== '';
|
|
819
850
|
}
|
|
820
851
|
/**
|
|
821
852
|
* Precondition: Must have pending changes to commit, they do not need to be staged.
|
|
@@ -824,16 +855,16 @@ function hasChangesToCommit() {
|
|
|
824
855
|
*/
|
|
825
856
|
function createCommit(message) {
|
|
826
857
|
// Stage entire working tree for commit.
|
|
827
|
-
(0,
|
|
858
|
+
(0, node_child_process_1.execSync)('git add -A', { encoding: 'utf8', stdio: 'pipe' });
|
|
828
859
|
// Commit with the message passed via stdin to avoid bash escaping issues.
|
|
829
|
-
(0,
|
|
860
|
+
(0, node_child_process_1.execSync)('git commit --no-verify -F -', { encoding: 'utf8', stdio: 'pipe', input: message });
|
|
830
861
|
}
|
|
831
862
|
/**
|
|
832
863
|
* @return The Git SHA hash of the HEAD commit. Returns null if unable to retrieve the hash.
|
|
833
864
|
*/
|
|
834
865
|
function findCurrentGitSha() {
|
|
835
866
|
try {
|
|
836
|
-
return (0,
|
|
867
|
+
return (0, node_child_process_1.execSync)('git rev-parse HEAD', { encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
837
868
|
}
|
|
838
869
|
catch {
|
|
839
870
|
return null;
|
package/src/utilities/color.d.ts
CHANGED
|
@@ -5,6 +5,5 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
declare
|
|
10
|
-
export { colors };
|
|
8
|
+
export { color as colors, figures } from 'listr2';
|
|
9
|
+
export declare function supportColor(stream?: NodeJS.WritableStream): boolean;
|