142 lines
4.3 KiB
TypeScript
142 lines
4.3 KiB
TypeScript
import axios from 'axios';
|
|
import { coerce, gt, maxSatisfying, SemVer } from 'semver';
|
|
|
|
type PackageSpec = string | { main: string; children: string[] };
|
|
const packagesToUpdate: PackageSpec[] = [
|
|
{
|
|
main: '@angular/cli',
|
|
children: [
|
|
'@angular-devkit/build-angular',
|
|
'@angular-devkit/core',
|
|
'@angular-devkit/schematics',
|
|
'@angular/build',
|
|
'@angular/pwa',
|
|
'@angular/ssr',
|
|
'@schematics/angular',
|
|
],
|
|
},
|
|
{
|
|
main: '@angular-devkit/architect',
|
|
children: ['@angular-devkit/build-webpack'],
|
|
},
|
|
{
|
|
main: '@angular/core',
|
|
children: [
|
|
'@angular/common',
|
|
'@angular/compiler',
|
|
'@angular/compiler-cli',
|
|
'@angular/localize',
|
|
'@angular/platform-browser',
|
|
'@angular/platform-server',
|
|
'@angular/router',
|
|
],
|
|
},
|
|
{
|
|
main: '@angular/material',
|
|
children: ['@angular/cdk', '@angular/google-maps'],
|
|
},
|
|
'ng-packagr',
|
|
];
|
|
|
|
// Resolved from `@angular/core`'s peerDependencies (not its own dist-tags) so it
|
|
// stays aligned with whatever range Angular actually accepts. Only zone.js: rxjs
|
|
// is intentionally excluded - Angular accepts a wide rxjs range (6 || 7), so we
|
|
// don't pin/bump it from here (which would otherwise force it into the migration).
|
|
const angularCorePeerResolvedPackages = ['zone.js'] as const;
|
|
|
|
export async function fetchVersionsFromRegistry(
|
|
targetVersion: 'latest' | 'next'
|
|
) {
|
|
console.log('⏳ - Fetching versions from registry...');
|
|
|
|
const packageVersionMap = new Map<string, string>();
|
|
await Promise.all(
|
|
packagesToUpdate.map((pkgSpec) =>
|
|
fetch(packageVersionMap, pkgSpec, targetVersion)
|
|
)
|
|
);
|
|
|
|
await resolveAngularCorePeerDependencies(packageVersionMap);
|
|
|
|
console.log('✅ - Finished fetching versions from registry');
|
|
|
|
return packageVersionMap;
|
|
}
|
|
|
|
async function resolveAngularCorePeerDependencies(
|
|
packageVersionMap: Map<string, string>
|
|
) {
|
|
const angularCoreVersion = packageVersionMap.get('@angular/core')!;
|
|
const { data } = await axios.get(
|
|
`https://registry.npmjs.org/@angular/core/${angularCoreVersion}`
|
|
);
|
|
const peerDependencies: Record<string, string> = data.peerDependencies ?? {};
|
|
|
|
await Promise.all(
|
|
angularCorePeerResolvedPackages.map(async (pkgName) => {
|
|
const peerRange = peerDependencies[pkgName];
|
|
if (!peerRange) {
|
|
console.warn(
|
|
` ⚠️ @angular/core@${angularCoreVersion} declares no peerDependency for "${pkgName}", skipping`
|
|
);
|
|
return;
|
|
}
|
|
|
|
const { data } = await axios.get(`https://registry.npmjs.org/${pkgName}`);
|
|
const resolved = maxSatisfying(
|
|
Object.keys(data.versions ?? {}),
|
|
peerRange,
|
|
{ includePrerelease: false }
|
|
);
|
|
if (!resolved) {
|
|
console.warn(
|
|
` ⚠️ Could not resolve a published version of "${pkgName}" matching peer range "${peerRange}"`
|
|
);
|
|
return;
|
|
}
|
|
|
|
packageVersionMap.set(pkgName, resolved);
|
|
console.log(` ${pkgName}: ${resolved}`);
|
|
})
|
|
);
|
|
}
|
|
|
|
async function fetch(
|
|
packageVersionMap: Map<string, string>,
|
|
pkgSpec: PackageSpec,
|
|
targetVersion: 'latest' | 'next'
|
|
) {
|
|
function setPackageVersions(pkgSpec: PackageSpec, version: string) {
|
|
if (typeof pkgSpec === 'string') {
|
|
packageVersionMap.set(pkgSpec, version);
|
|
return;
|
|
}
|
|
|
|
packageVersionMap.set(pkgSpec.main, version);
|
|
for (const child of pkgSpec.children) {
|
|
packageVersionMap.set(child, version);
|
|
}
|
|
}
|
|
|
|
const pkgName = typeof pkgSpec === 'string' ? pkgSpec : pkgSpec.main;
|
|
// set it to empty initially to keep the order of the specified packages
|
|
setPackageVersions(pkgSpec, '');
|
|
|
|
const response = await axios.get(`https://registry.npmjs.org/${pkgName}`);
|
|
const distTags = response.data['dist-tags'];
|
|
const latestVersion = distTags['latest'];
|
|
if (targetVersion === 'latest') {
|
|
setPackageVersions(pkgSpec, latestVersion);
|
|
console.log(` ${pkgName}: ${latestVersion}`);
|
|
} else {
|
|
const nextVersion = distTags['next'] ?? latestVersion;
|
|
const coercedNextVersion = coerce(nextVersion) as SemVer;
|
|
// check which is the greater version
|
|
const versionToUse = gt(coercedNextVersion, latestVersion)
|
|
? nextVersion
|
|
: latestVersion;
|
|
setPackageVersions(pkgSpec, versionToUse);
|
|
console.log(` ${pkgName}: ${versionToUse}`);
|
|
}
|
|
}
|