source: trip-planner-front/node_modules/@angular/cli/src/commands/update/schematic/index.js@ 6c1585f

Last change on this file since 6c1585f was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 29.1 KB
Line 
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
12}) : (function(o, m, k, k2) {
13 if (k2 === undefined) k2 = k;
14 o[k2] = m[k];
15}));
16var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17 Object.defineProperty(o, "default", { enumerable: true, value: v });
18}) : function(o, v) {
19 o["default"] = v;
20});
21var __importStar = (this && this.__importStar) || function (mod) {
22 if (mod && mod.__esModule) return mod;
23 var result = {};
24 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25 __setModuleDefault(result, mod);
26 return result;
27};
28Object.defineProperty(exports, "__esModule", { value: true });
29exports.angularMajorCompatGuarantee = void 0;
30const core_1 = require("@angular-devkit/core");
31const schematics_1 = require("@angular-devkit/schematics");
32const npa = __importStar(require("npm-package-arg"));
33const semver = __importStar(require("semver"));
34const package_metadata_1 = require("../../../../utilities/package-metadata");
35// Angular guarantees that a major is compatible with its following major (so packages that depend
36// on Angular 5 are also compatible with Angular 6). This is, in code, represented by verifying
37// that all other packages that have a peer dependency of `"@angular/core": "^5.0.0"` actually
38// supports 6.0, by adding that compatibility to the range, so it is `^5.0.0 || ^6.0.0`.
39// We export it to allow for testing.
40function angularMajorCompatGuarantee(range) {
41 let newRange = semver.validRange(range);
42 if (!newRange) {
43 return range;
44 }
45 let major = 1;
46 while (!semver.gtr(major + '.0.0', newRange)) {
47 major++;
48 if (major >= 99) {
49 // Use original range if it supports a major this high
50 // Range is most likely unbounded (e.g., >=5.0.0)
51 return newRange;
52 }
53 }
54 // Add the major version as compatible with the angular compatible, with all minors. This is
55 // already one major above the greatest supported, because we increment `major` before checking.
56 // We add minors like this because a minor beta is still compatible with a minor non-beta.
57 newRange = range;
58 for (let minor = 0; minor < 20; minor++) {
59 newRange += ` || ^${major}.${minor}.0-alpha.0 `;
60 }
61 return semver.validRange(newRange) || range;
62}
63exports.angularMajorCompatGuarantee = angularMajorCompatGuarantee;
64// This is a map of packageGroupName to range extending function. If it isn't found, the range is
65// kept the same.
66const knownPeerCompatibleList = {
67 '@angular/core': angularMajorCompatGuarantee,
68};
69function _updatePeerVersion(infoMap, name, range) {
70 // Resolve packageGroupName.
71 const maybePackageInfo = infoMap.get(name);
72 if (!maybePackageInfo) {
73 return range;
74 }
75 if (maybePackageInfo.target) {
76 name = maybePackageInfo.target.updateMetadata.packageGroupName || name;
77 }
78 else {
79 name = maybePackageInfo.installed.updateMetadata.packageGroupName || name;
80 }
81 const maybeTransform = knownPeerCompatibleList[name];
82 if (maybeTransform) {
83 if (typeof maybeTransform == 'function') {
84 return maybeTransform(range);
85 }
86 else {
87 return maybeTransform;
88 }
89 }
90 return range;
91}
92function _validateForwardPeerDependencies(name, infoMap, peers, peersMeta, logger, next) {
93 let validationFailed = false;
94 for (const [peer, range] of Object.entries(peers)) {
95 logger.debug(`Checking forward peer ${peer}...`);
96 const maybePeerInfo = infoMap.get(peer);
97 const isOptional = peersMeta[peer] && !!peersMeta[peer].optional;
98 if (!maybePeerInfo) {
99 if (!isOptional) {
100 logger.warn([
101 `Package ${JSON.stringify(name)} has a missing peer dependency of`,
102 `${JSON.stringify(peer)} @ ${JSON.stringify(range)}.`,
103 ].join(' '));
104 }
105 continue;
106 }
107 const peerVersion = maybePeerInfo.target && maybePeerInfo.target.packageJson.version
108 ? maybePeerInfo.target.packageJson.version
109 : maybePeerInfo.installed.version;
110 logger.debug(` Range intersects(${range}, ${peerVersion})...`);
111 if (!semver.satisfies(peerVersion, range, { includePrerelease: next || undefined })) {
112 logger.error([
113 `Package ${JSON.stringify(name)} has an incompatible peer dependency to`,
114 `${JSON.stringify(peer)} (requires ${JSON.stringify(range)},`,
115 `would install ${JSON.stringify(peerVersion)})`,
116 ].join(' '));
117 validationFailed = true;
118 continue;
119 }
120 }
121 return validationFailed;
122}
123function _validateReversePeerDependencies(name, version, infoMap, logger, next) {
124 for (const [installed, installedInfo] of infoMap.entries()) {
125 const installedLogger = logger.createChild(installed);
126 installedLogger.debug(`${installed}...`);
127 const peers = (installedInfo.target || installedInfo.installed).packageJson.peerDependencies;
128 for (const [peer, range] of Object.entries(peers || {})) {
129 if (peer != name) {
130 // Only check peers to the packages we're updating. We don't care about peers
131 // that are unmet but we have no effect on.
132 continue;
133 }
134 // Ignore peerDependency mismatches for these packages.
135 // They are deprecated and removed via a migration.
136 const ignoredPackages = [
137 'codelyzer',
138 '@schematics/update',
139 '@angular-devkit/build-ng-packagr',
140 'tsickle',
141 ];
142 if (ignoredPackages.includes(installed)) {
143 continue;
144 }
145 // Override the peer version range if it's known as a compatible.
146 const extendedRange = _updatePeerVersion(infoMap, peer, range);
147 if (!semver.satisfies(version, extendedRange, { includePrerelease: next || undefined })) {
148 logger.error([
149 `Package ${JSON.stringify(installed)} has an incompatible peer dependency to`,
150 `${JSON.stringify(name)} (requires`,
151 `${JSON.stringify(range)}${extendedRange == range ? '' : ' (extended)'},`,
152 `would install ${JSON.stringify(version)}).`,
153 ].join(' '));
154 return true;
155 }
156 }
157 }
158 return false;
159}
160function _validateUpdatePackages(infoMap, force, next, logger) {
161 logger.debug('Updating the following packages:');
162 infoMap.forEach((info) => {
163 if (info.target) {
164 logger.debug(` ${info.name} => ${info.target.version}`);
165 }
166 });
167 let peerErrors = false;
168 infoMap.forEach((info) => {
169 const { name, target } = info;
170 if (!target) {
171 return;
172 }
173 const pkgLogger = logger.createChild(name);
174 logger.debug(`${name}...`);
175 const { peerDependencies = {}, peerDependenciesMeta = {} } = target.packageJson;
176 peerErrors =
177 _validateForwardPeerDependencies(name, infoMap, peerDependencies, peerDependenciesMeta, pkgLogger, next) || peerErrors;
178 peerErrors =
179 _validateReversePeerDependencies(name, target.version, infoMap, pkgLogger, next) ||
180 peerErrors;
181 });
182 if (!force && peerErrors) {
183 throw new schematics_1.SchematicsException(core_1.tags.stripIndents `Incompatible peer dependencies found.
184 Peer dependency warnings when installing dependencies means that those dependencies might not work correctly together.
185 You can use the '--force' option to ignore incompatible peer dependencies and instead address these warnings later.`);
186 }
187}
188function _performUpdate(tree, context, infoMap, logger, migrateOnly) {
189 const packageJsonContent = tree.read('/package.json');
190 if (!packageJsonContent) {
191 throw new schematics_1.SchematicsException('Could not find a package.json. Are you in a Node project?');
192 }
193 let packageJson;
194 try {
195 packageJson = JSON.parse(packageJsonContent.toString());
196 }
197 catch (e) {
198 throw new schematics_1.SchematicsException('package.json could not be parsed: ' + e.message);
199 }
200 const updateDependency = (deps, name, newVersion) => {
201 const oldVersion = deps[name];
202 // We only respect caret and tilde ranges on update.
203 const execResult = /^[\^~]/.exec(oldVersion);
204 deps[name] = `${execResult ? execResult[0] : ''}${newVersion}`;
205 };
206 const toInstall = [...infoMap.values()]
207 .map((x) => [x.name, x.target, x.installed])
208 .filter(([name, target, installed]) => {
209 return !!name && !!target && !!installed;
210 });
211 toInstall.forEach(([name, target, installed]) => {
212 logger.info(`Updating package.json with dependency ${name} ` +
213 `@ ${JSON.stringify(target.version)} (was ${JSON.stringify(installed.version)})...`);
214 if (packageJson.dependencies && packageJson.dependencies[name]) {
215 updateDependency(packageJson.dependencies, name, target.version);
216 if (packageJson.devDependencies && packageJson.devDependencies[name]) {
217 delete packageJson.devDependencies[name];
218 }
219 if (packageJson.peerDependencies && packageJson.peerDependencies[name]) {
220 delete packageJson.peerDependencies[name];
221 }
222 }
223 else if (packageJson.devDependencies && packageJson.devDependencies[name]) {
224 updateDependency(packageJson.devDependencies, name, target.version);
225 if (packageJson.peerDependencies && packageJson.peerDependencies[name]) {
226 delete packageJson.peerDependencies[name];
227 }
228 }
229 else if (packageJson.peerDependencies && packageJson.peerDependencies[name]) {
230 updateDependency(packageJson.peerDependencies, name, target.version);
231 }
232 else {
233 logger.warn(`Package ${name} was not found in dependencies.`);
234 }
235 });
236 const newContent = JSON.stringify(packageJson, null, 2);
237 if (packageJsonContent.toString() != newContent || migrateOnly) {
238 if (!migrateOnly) {
239 tree.overwrite('/package.json', JSON.stringify(packageJson, null, 2));
240 }
241 const externalMigrations = [];
242 // Run the migrate schematics with the list of packages to use. The collection contains
243 // version information and we need to do this post installation. Please note that the
244 // migration COULD fail and leave side effects on disk.
245 // Run the schematics task of those packages.
246 toInstall.forEach(([name, target, installed]) => {
247 if (!target.updateMetadata.migrations) {
248 return;
249 }
250 const collection = (target.updateMetadata.migrations.match(/^[./]/) ? name + '/' : '') +
251 target.updateMetadata.migrations;
252 externalMigrations.push({
253 package: name,
254 collection,
255 from: installed.version,
256 to: target.version,
257 });
258 return;
259 });
260 if (externalMigrations.length > 0) {
261 // eslint-disable-next-line @typescript-eslint/no-explicit-any
262 global.externalMigrations = externalMigrations;
263 }
264 }
265}
266function _getUpdateMetadata(packageJson, logger) {
267 const metadata = packageJson['ng-update'];
268 const result = {
269 packageGroup: {},
270 requirements: {},
271 };
272 if (!metadata || typeof metadata != 'object' || Array.isArray(metadata)) {
273 return result;
274 }
275 if (metadata['packageGroup']) {
276 const packageGroup = metadata['packageGroup'];
277 // Verify that packageGroup is an array of strings or an map of versions. This is not an error
278 // but we still warn the user and ignore the packageGroup keys.
279 if (Array.isArray(packageGroup) && packageGroup.every((x) => typeof x == 'string')) {
280 result.packageGroup = packageGroup.reduce((group, name) => {
281 group[name] = packageJson.version;
282 return group;
283 }, result.packageGroup);
284 }
285 else if (typeof packageGroup == 'object' &&
286 packageGroup &&
287 Object.values(packageGroup).every((x) => typeof x == 'string')) {
288 result.packageGroup = packageGroup;
289 }
290 else {
291 logger.warn(`packageGroup metadata of package ${packageJson.name} is malformed. Ignoring.`);
292 }
293 result.packageGroupName = Object.keys(result.packageGroup)[0];
294 }
295 if (typeof metadata['packageGroupName'] == 'string') {
296 result.packageGroupName = metadata['packageGroupName'];
297 }
298 if (metadata['requirements']) {
299 const requirements = metadata['requirements'];
300 // Verify that requirements are
301 if (typeof requirements != 'object' ||
302 Array.isArray(requirements) ||
303 Object.keys(requirements).some((name) => typeof requirements[name] != 'string')) {
304 logger.warn(`requirements metadata of package ${packageJson.name} is malformed. Ignoring.`);
305 }
306 else {
307 result.requirements = requirements;
308 }
309 }
310 if (metadata['migrations']) {
311 const migrations = metadata['migrations'];
312 if (typeof migrations != 'string') {
313 logger.warn(`migrations metadata of package ${packageJson.name} is malformed. Ignoring.`);
314 }
315 else {
316 result.migrations = migrations;
317 }
318 }
319 return result;
320}
321function _usageMessage(options, infoMap, logger) {
322 const packageGroups = new Map();
323 const packagesToUpdate = [...infoMap.entries()]
324 .map(([name, info]) => {
325 const tag = options.next
326 ? info.npmPackageJson['dist-tags']['next']
327 ? 'next'
328 : 'latest'
329 : 'latest';
330 const version = info.npmPackageJson['dist-tags'][tag];
331 const target = info.npmPackageJson.versions[version];
332 return {
333 name,
334 info,
335 version,
336 tag,
337 target,
338 };
339 })
340 .filter(({ info, version, target }) => {
341 return target && semver.compare(info.installed.version, version) < 0;
342 })
343 .filter(({ target }) => {
344 return target['ng-update'];
345 })
346 .map(({ name, info, version, tag, target }) => {
347 // Look for packageGroup.
348 if (target['ng-update'] && target['ng-update']['packageGroup']) {
349 const packageGroup = target['ng-update']['packageGroup'];
350 const packageGroupName = target['ng-update']['packageGroupName'] || target['ng-update']['packageGroup'][0];
351 if (packageGroupName) {
352 if (packageGroups.has(name)) {
353 return null;
354 }
355 packageGroup.forEach((x) => packageGroups.set(x, packageGroupName));
356 packageGroups.set(packageGroupName, packageGroupName);
357 name = packageGroupName;
358 }
359 }
360 let command = `ng update ${name}`;
361 if (tag == 'next') {
362 command += ' --next';
363 }
364 return [name, `${info.installed.version} -> ${version} `, command];
365 })
366 .filter((x) => x !== null)
367 .sort((a, b) => (a && b ? a[0].localeCompare(b[0]) : 0));
368 if (packagesToUpdate.length == 0) {
369 logger.info('We analyzed your package.json and everything seems to be in order. Good work!');
370 return;
371 }
372 logger.info('We analyzed your package.json, there are some packages to update:\n');
373 // Find the largest name to know the padding needed.
374 let namePad = Math.max(...[...infoMap.keys()].map((x) => x.length)) + 2;
375 if (!Number.isFinite(namePad)) {
376 namePad = 30;
377 }
378 const pads = [namePad, 25, 0];
379 logger.info(' ' + ['Name', 'Version', 'Command to update'].map((x, i) => x.padEnd(pads[i])).join(''));
380 logger.info(' ' + '-'.repeat(pads.reduce((s, x) => (s += x), 0) + 20));
381 packagesToUpdate.forEach((fields) => {
382 if (!fields) {
383 return;
384 }
385 logger.info(' ' + fields.map((x, i) => x.padEnd(pads[i])).join(''));
386 });
387 logger.info(`\nThere might be additional packages which don't provide 'ng update' capabilities that are outdated.\n` +
388 `You can update the additional packages by running the update command of your package manager.`);
389 return;
390}
391function _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger) {
392 const name = npmPackageJson.name;
393 const packageJsonRange = allDependencies.get(name);
394 if (!packageJsonRange) {
395 throw new schematics_1.SchematicsException(`Package ${JSON.stringify(name)} was not found in package.json.`);
396 }
397 // Find out the currently installed version. Either from the package.json or the node_modules/
398 // TODO: figure out a way to read package-lock.json and/or yarn.lock.
399 let installedVersion;
400 const packageContent = tree.read(`/node_modules/${name}/package.json`);
401 if (packageContent) {
402 const content = JSON.parse(packageContent.toString());
403 installedVersion = content.version;
404 }
405 if (!installedVersion) {
406 // Find the version from NPM that fits the range to max.
407 installedVersion = semver.maxSatisfying(Object.keys(npmPackageJson.versions), packageJsonRange);
408 }
409 if (!installedVersion) {
410 throw new schematics_1.SchematicsException(`An unexpected error happened; could not determine version for package ${name}.`);
411 }
412 const installedPackageJson = npmPackageJson.versions[installedVersion] || packageContent;
413 if (!installedPackageJson) {
414 throw new schematics_1.SchematicsException(`An unexpected error happened; package ${name} has no version ${installedVersion}.`);
415 }
416 let targetVersion = packages.get(name);
417 if (targetVersion) {
418 if (npmPackageJson['dist-tags'][targetVersion]) {
419 targetVersion = npmPackageJson['dist-tags'][targetVersion];
420 }
421 else if (targetVersion == 'next') {
422 targetVersion = npmPackageJson['dist-tags']['latest'];
423 }
424 else {
425 targetVersion = semver.maxSatisfying(Object.keys(npmPackageJson.versions), targetVersion);
426 }
427 }
428 if (targetVersion && semver.lte(targetVersion, installedVersion)) {
429 logger.debug(`Package ${name} already satisfied by package.json (${packageJsonRange}).`);
430 targetVersion = undefined;
431 }
432 const target = targetVersion
433 ? {
434 version: targetVersion,
435 packageJson: npmPackageJson.versions[targetVersion],
436 updateMetadata: _getUpdateMetadata(npmPackageJson.versions[targetVersion], logger),
437 }
438 : undefined;
439 // Check if there's an installed version.
440 return {
441 name,
442 npmPackageJson,
443 installed: {
444 version: installedVersion,
445 packageJson: installedPackageJson,
446 updateMetadata: _getUpdateMetadata(installedPackageJson, logger),
447 },
448 target,
449 packageJsonRange,
450 };
451}
452function _buildPackageList(options, projectDeps, logger) {
453 // Parse the packages options to set the targeted version.
454 const packages = new Map();
455 const commandLinePackages = options.packages && options.packages.length > 0 ? options.packages : [];
456 for (const pkg of commandLinePackages) {
457 // Split the version asked on command line.
458 const m = pkg.match(/^((?:@[^/]{1,100}\/)?[^@]{1,100})(?:@(.{1,100}))?$/);
459 if (!m) {
460 logger.warn(`Invalid package argument: ${JSON.stringify(pkg)}. Skipping.`);
461 continue;
462 }
463 const [, npmName, maybeVersion] = m;
464 const version = projectDeps.get(npmName);
465 if (!version) {
466 logger.warn(`Package not installed: ${JSON.stringify(npmName)}. Skipping.`);
467 continue;
468 }
469 packages.set(npmName, (maybeVersion || (options.next ? 'next' : 'latest')));
470 }
471 return packages;
472}
473function _addPackageGroup(tree, packages, allDependencies, npmPackageJson, logger) {
474 const maybePackage = packages.get(npmPackageJson.name);
475 if (!maybePackage) {
476 return;
477 }
478 const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger);
479 const version = (info.target && info.target.version) ||
480 npmPackageJson['dist-tags'][maybePackage] ||
481 maybePackage;
482 if (!npmPackageJson.versions[version]) {
483 return;
484 }
485 const ngUpdateMetadata = npmPackageJson.versions[version]['ng-update'];
486 if (!ngUpdateMetadata) {
487 return;
488 }
489 let packageGroup = ngUpdateMetadata['packageGroup'];
490 if (!packageGroup) {
491 return;
492 }
493 if (Array.isArray(packageGroup) && !packageGroup.some((x) => typeof x != 'string')) {
494 packageGroup = packageGroup.reduce((acc, curr) => {
495 acc[curr] = maybePackage;
496 return acc;
497 }, {});
498 }
499 // Only need to check if it's an object because we set it right the time before.
500 if (typeof packageGroup != 'object' ||
501 packageGroup === null ||
502 Object.values(packageGroup).some((v) => typeof v != 'string')) {
503 logger.warn(`packageGroup metadata of package ${npmPackageJson.name} is malformed.`);
504 return;
505 }
506 Object.keys(packageGroup)
507 .filter((name) => !packages.has(name)) // Don't override names from the command line.
508 .filter((name) => allDependencies.has(name)) // Remove packages that aren't installed.
509 .forEach((name) => {
510 packages.set(name, packageGroup[name]);
511 });
512}
513/**
514 * Add peer dependencies of packages on the command line to the list of packages to update.
515 * We don't do verification of the versions here as this will be done by a later step (and can
516 * be ignored by the --force flag).
517 * @private
518 */
519function _addPeerDependencies(tree, packages, allDependencies, npmPackageJson, npmPackageJsonMap, logger) {
520 const maybePackage = packages.get(npmPackageJson.name);
521 if (!maybePackage) {
522 return;
523 }
524 const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger);
525 const version = (info.target && info.target.version) ||
526 npmPackageJson['dist-tags'][maybePackage] ||
527 maybePackage;
528 if (!npmPackageJson.versions[version]) {
529 return;
530 }
531 const packageJson = npmPackageJson.versions[version];
532 const error = false;
533 for (const [peer, range] of Object.entries(packageJson.peerDependencies || {})) {
534 if (packages.has(peer)) {
535 continue;
536 }
537 const peerPackageJson = npmPackageJsonMap.get(peer);
538 if (peerPackageJson) {
539 const peerInfo = _buildPackageInfo(tree, packages, allDependencies, peerPackageJson, logger);
540 if (semver.satisfies(peerInfo.installed.version, range)) {
541 continue;
542 }
543 }
544 packages.set(peer, range);
545 }
546 if (error) {
547 throw new schematics_1.SchematicsException('An error occured, see above.');
548 }
549}
550function _getAllDependencies(tree) {
551 const packageJsonContent = tree.read('/package.json');
552 if (!packageJsonContent) {
553 throw new schematics_1.SchematicsException('Could not find a package.json. Are you in a Node project?');
554 }
555 let packageJson;
556 try {
557 packageJson = JSON.parse(packageJsonContent.toString());
558 }
559 catch (e) {
560 throw new schematics_1.SchematicsException('package.json could not be parsed: ' + e.message);
561 }
562 return [
563 ...Object.entries(packageJson.peerDependencies || {}),
564 ...Object.entries(packageJson.devDependencies || {}),
565 ...Object.entries(packageJson.dependencies || {}),
566 ];
567}
568function _formatVersion(version) {
569 if (version === undefined) {
570 return undefined;
571 }
572 if (!version.match(/^\d{1,30}\.\d{1,30}\.\d{1,30}/)) {
573 version += '.0';
574 }
575 if (!version.match(/^\d{1,30}\.\d{1,30}\.\d{1,30}/)) {
576 version += '.0';
577 }
578 if (!semver.valid(version)) {
579 throw new schematics_1.SchematicsException(`Invalid migration version: ${JSON.stringify(version)}`);
580 }
581 return version;
582}
583/**
584 * Returns whether or not the given package specifier (the value string in a
585 * `package.json` dependency) is hosted in the NPM registry.
586 * @throws When the specifier cannot be parsed.
587 */
588function isPkgFromRegistry(name, specifier) {
589 const result = npa.resolve(name, specifier);
590 return !!result.registry;
591}
592function default_1(options) {
593 if (!options.packages) {
594 // We cannot just return this because we need to fetch the packages from NPM still for the
595 // help/guide to show.
596 options.packages = [];
597 }
598 else {
599 // We split every packages by commas to allow people to pass in multiple and make it an array.
600 options.packages = options.packages.reduce((acc, curr) => {
601 return acc.concat(curr.split(','));
602 }, []);
603 }
604 if (options.migrateOnly && options.from) {
605 if (options.packages.length !== 1) {
606 throw new schematics_1.SchematicsException('--from requires that only a single package be passed.');
607 }
608 }
609 options.from = _formatVersion(options.from);
610 options.to = _formatVersion(options.to);
611 const usingYarn = options.packageManager === 'yarn';
612 return async (tree, context) => {
613 const logger = context.logger;
614 const npmDeps = new Map(_getAllDependencies(tree).filter(([name, specifier]) => {
615 try {
616 return isPkgFromRegistry(name, specifier);
617 }
618 catch {
619 logger.warn(`Package ${name} was not found on the registry. Skipping.`);
620 return false;
621 }
622 }));
623 const packages = _buildPackageList(options, npmDeps, logger);
624 // Grab all package.json from the npm repository. This requires a lot of HTTP calls so we
625 // try to parallelize as many as possible.
626 const allPackageMetadata = await Promise.all(Array.from(npmDeps.keys()).map((depName) => package_metadata_1.getNpmPackageJson(depName, logger, {
627 registry: options.registry,
628 usingYarn,
629 verbose: options.verbose,
630 })));
631 // Build a map of all dependencies and their packageJson.
632 const npmPackageJsonMap = allPackageMetadata.reduce((acc, npmPackageJson) => {
633 // If the package was not found on the registry. It could be private, so we will just
634 // ignore. If the package was part of the list, we will error out, but will simply ignore
635 // if it's either not requested (so just part of package.json. silently) or if it's a
636 // `--all` situation. There is an edge case here where a public package peer depends on a
637 // private one, but it's rare enough.
638 if (!npmPackageJson.name) {
639 if (npmPackageJson.requestedName && packages.has(npmPackageJson.requestedName)) {
640 throw new schematics_1.SchematicsException(`Package ${JSON.stringify(npmPackageJson.requestedName)} was not found on the ` +
641 'registry. Cannot continue as this may be an error.');
642 }
643 }
644 else {
645 // If a name is present, it is assumed to be fully populated
646 acc.set(npmPackageJson.name, npmPackageJson);
647 }
648 return acc;
649 }, new Map());
650 // Augment the command line package list with packageGroups and forward peer dependencies.
651 // Each added package may uncover new package groups and peer dependencies, so we must
652 // repeat this process until the package list stabilizes.
653 let lastPackagesSize;
654 do {
655 lastPackagesSize = packages.size;
656 npmPackageJsonMap.forEach((npmPackageJson) => {
657 _addPackageGroup(tree, packages, npmDeps, npmPackageJson, logger);
658 _addPeerDependencies(tree, packages, npmDeps, npmPackageJson, npmPackageJsonMap, logger);
659 });
660 } while (packages.size > lastPackagesSize);
661 // Build the PackageInfo for each module.
662 const packageInfoMap = new Map();
663 npmPackageJsonMap.forEach((npmPackageJson) => {
664 packageInfoMap.set(npmPackageJson.name, _buildPackageInfo(tree, packages, npmDeps, npmPackageJson, logger));
665 });
666 // Now that we have all the information, check the flags.
667 if (packages.size > 0) {
668 if (options.migrateOnly && options.from && options.packages) {
669 return;
670 }
671 const sublog = new core_1.logging.LevelCapLogger('validation', logger.createChild(''), 'warn');
672 _validateUpdatePackages(packageInfoMap, !!options.force, !!options.next, sublog);
673 _performUpdate(tree, context, packageInfoMap, logger, !!options.migrateOnly);
674 }
675 else {
676 _usageMessage(options, packageInfoMap, logger);
677 }
678 };
679}
680exports.default = default_1;
Note: See TracBrowser for help on using the repository browser.