ng-upgrade-orchestrator
Version:
Enterprise-grade Angular Multi-Version Upgrade Orchestrator with automatic npm installation, comprehensive dependency management, and seamless integration of all 9 official Angular migrations. Safely migrate Angular applications across multiple major vers
268 lines • 10.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpgradePathCalculator = void 0;
const VersionHandlerRegistry_1 = require("./VersionHandlerRegistry");
class UpgradePathCalculator {
versionHandlers;
supportedVersions = ['12', '13', '14', '15', '16', '17', '18', '19', '20'];
constructor() {
this.versionHandlers = new VersionHandlerRegistry_1.VersionHandlerRegistry();
}
/**
* Calculate optimal upgrade path from current to target version
*/
async calculatePath(currentVersion, targetVersion, options) {
// Validate version compatibility
this.validateVersions(currentVersion, targetVersion);
// Generate version sequence
const versionSequence = this.generateVersionSequence(currentVersion.major, targetVersion.major);
// Create upgrade steps
const steps = await this.createUpgradeSteps(versionSequence, options);
return {
from: currentVersion,
to: targetVersion,
steps
};
}
/**
* Generate sequence of versions for upgrade path
*/
generateVersionSequence(fromMajor, toMajor) {
if (fromMajor >= toMajor) {
throw new Error(`Cannot upgrade from version ${fromMajor} to ${toMajor}. Target version must be higher.`);
}
const sequence = [];
for (let version = fromMajor + 1; version <= toMajor; version++) {
if (this.supportedVersions.includes(version.toString())) {
sequence.push(version.toString());
}
else {
throw new Error(`Angular version ${version} is not supported for upgrade`);
}
}
return sequence;
}
/**
* Create upgrade steps for version sequence
*/
async createUpgradeSteps(versionSequence, options) {
const steps = [];
for (let i = 0; i < versionSequence.length; i++) {
const fromVersion = i === 0 ? 'current' : versionSequence[i - 1];
const toVersion = versionSequence[i];
const step = await this.createUpgradeStep(fromVersion, toVersion, options);
steps.push(step);
}
return steps;
}
/**
* Create individual upgrade step
*/
async createUpgradeStep(fromVersion, toVersion, options) {
const handler = this.versionHandlers.getHandler(toVersion);
if (!handler) {
throw new Error(`No handler found for Angular version ${toVersion}`);
}
// Get prerequisites for this version
const prerequisites = this.getPrerequisites(toVersion);
// Get breaking changes for this version
const breakingChanges = handler.getBreakingChanges();
// Get validation steps
const validations = this.getValidationSteps(toVersion, options);
return {
fromVersion,
toVersion,
required: true,
handler: `Angular${toVersion}Handler`,
prerequisites,
breakingChanges,
validations
};
}
/**
* Get prerequisites for specific Angular version
*/
getPrerequisites(version) {
const prerequisites = [];
// Node.js requirements by Angular version
const nodeRequirements = {
'12': '>=12.20.0',
'13': '>=12.20.0',
'14': '>=14.15.0',
'15': '>=14.20.0',
'16': '>=16.14.0',
'17': '>=18.13.0',
'18': '>=18.19.1',
'19': '>=18.19.1',
'20': '>=18.19.1'
};
// TypeScript requirements by Angular version
const tsRequirements = {
'12': '>=4.2.3 <4.4.0',
'13': '>=4.4.2 <4.6.0',
'14': '>=4.7.2 <4.8.0',
'15': '>=4.8.2 <4.10.0',
'16': '>=4.9.3 <5.1.0',
'17': '>=5.2.0 <5.3.0',
'18': '>=5.4.0 <5.5.0',
'19': '>=5.5.0 <5.6.0',
'20': '>=5.6.0 <5.7.0'
};
// Add Node.js prerequisite
if (nodeRequirements[version]) {
prerequisites.push({
type: 'node',
name: 'Node.js',
requiredVersion: nodeRequirements[version],
compatibleVersions: [nodeRequirements[version]],
critical: true
});
}
// Add TypeScript prerequisite
if (tsRequirements[version]) {
prerequisites.push({
type: 'typescript',
name: 'TypeScript',
requiredVersion: tsRequirements[version],
compatibleVersions: [tsRequirements[version]],
critical: true
});
}
// Add Angular CLI prerequisite
prerequisites.push({
type: 'dependency',
name: '@angular/cli',
requiredVersion: `^${version}.0.0`,
compatibleVersions: [`^${version}.0.0`],
critical: true
});
return prerequisites;
}
/**
* Get validation steps for version
*/
getValidationSteps(version, options) {
const validations = [
{
type: 'build',
command: 'npm run build',
timeout: 300000,
required: true,
description: `Validate build after Angular ${version} upgrade`
}
];
if (options.validationLevel === 'comprehensive') {
validations.push({
type: 'test',
command: 'npm test -- --watch=false',
timeout: 600000,
required: true,
description: `Run tests after Angular ${version} upgrade`
}, {
type: 'lint',
command: 'npm run lint',
timeout: 120000,
required: false,
description: `Lint code after Angular ${version} upgrade`
});
}
return validations;
}
/**
* Validate version compatibility
*/
validateVersions(currentVersion, targetVersion) {
if (currentVersion.major >= targetVersion.major) {
throw new Error(`Invalid upgrade path: Cannot upgrade from ${currentVersion.full} to ${targetVersion.full}. ` +
'Target version must be higher than current version.');
}
if (!this.supportedVersions.includes(currentVersion.major.toString())) {
throw new Error(`Current Angular version ${currentVersion.major} is not supported. ` +
`Supported versions: ${this.supportedVersions.join(', ')}`);
}
if (!this.supportedVersions.includes(targetVersion.major.toString())) {
throw new Error(`Target Angular version ${targetVersion.major} is not supported. ` +
`Supported versions: ${this.supportedVersions.join(', ')}`);
}
// Check for version gaps
const versionGap = targetVersion.major - currentVersion.major;
if (versionGap > 8) {
throw new Error(`Large version gap detected (${versionGap} major versions). ` +
'Consider upgrading in smaller increments for safety.');
}
}
/**
* Get estimated upgrade time
*/
getEstimatedUpgradeTime(path, options) {
let baseTimePerStep = 15; // minutes
// Adjust based on strategy
switch (options.strategy) {
case 'conservative':
baseTimePerStep *= 1.5;
break;
case 'progressive':
baseTimePerStep *= 0.8;
break;
}
// Adjust based on validation level
if (options.validationLevel === 'comprehensive') {
baseTimePerStep *= 1.3;
}
return path.steps.length * baseTimePerStep;
}
/**
* Get upgrade complexity score
*/
getUpgradeComplexity(path) {
let score = 0;
const factors = [];
// Base complexity per step
score += path.steps.length * 10;
// Breaking changes complexity
for (const step of path.steps) {
const criticalChanges = step.breakingChanges.filter(bc => bc.severity === 'critical').length;
const highChanges = step.breakingChanges.filter(bc => bc.severity === 'high').length;
score += criticalChanges * 20;
score += highChanges * 10;
if (criticalChanges > 0) {
factors.push(`Angular ${step.toVersion}: ${criticalChanges} critical breaking changes`);
}
}
// Large version jumps
const versionJump = path.to.major - path.from.major;
if (versionJump > 4) {
score += versionJump * 5;
factors.push(`Large version jump: ${versionJump} major versions`);
}
// Specific version complications
const complicatedVersions = ['13', '15', '17']; // Known complex upgrades
for (const step of path.steps) {
if (complicatedVersions.includes(step.toVersion)) {
score += 15;
factors.push(`Angular ${step.toVersion} includes significant architectural changes`);
}
}
return { score, factors };
}
/**
* Optimize upgrade path based on project analysis
*/
async optimizePath(path, projectAnalysis, options) {
// For now, return the original path
// In a full implementation, this would analyze the project
// and potentially suggest alternative paths or optimizations
return path;
}
/**
* Get alternative upgrade paths
*/
getAlternativePaths(currentVersion, targetVersion) {
// For now, return empty array
// In a full implementation, this could suggest different strategies
// like skipping intermediate versions where safe
return [];
}
}
exports.UpgradePathCalculator = UpgradePathCalculator;
//# sourceMappingURL=UpgradePathCalculator.js.map