UNPKG

marketing-post-generator-mcp

Version:

A powerful MCP server for AI-powered marketing blog post generation with Claude integration

290 lines 10.6 kB
import { VersionError, } from './types.js'; /** * Manages versioning for registry entries with semantic versioning support */ export class VersionManager { migrationHandlers = new Map(); compatibilityRules = new Map(); constructor() { // Set up default compatibility rules this.setupDefaultCompatibilityRules(); } /** * Parse version string to VersionInfo object */ parseVersion(versionString) { const versionPattern = /^(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.-]+))?$/; const match = versionString.match(versionPattern); if (!match) { throw new VersionError(`Invalid version format: ${versionString}. Expected format: x.y.z or x.y.z-prerelease`); } const result = { major: parseInt(match[1], 10), minor: parseInt(match[2], 10), patch: parseInt(match[3], 10), }; if (match[4]) { result.prerelease = match[4]; } return result; } /** * Format VersionInfo object to version string */ formatVersion(version) { let versionString = `${version.major}.${version.minor}.${version.patch}`; if (version.prerelease) { versionString += `-${version.prerelease}`; } return versionString; } /** * Compare two versions * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2 */ compareVersions(v1, v2) { // Compare major version if (v1.major !== v2.major) { return v1.major - v2.major; } // Compare minor version if (v1.minor !== v2.minor) { return v1.minor - v2.minor; } // Compare patch version if (v1.patch !== v2.patch) { return v1.patch - v2.patch; } // Compare prerelease if (v1.prerelease && v2.prerelease) { return v1.prerelease.localeCompare(v2.prerelease); } else if (v1.prerelease && !v2.prerelease) { return -1; // prerelease is less than release } else if (!v1.prerelease && v2.prerelease) { return 1; // release is greater than prerelease } return 0; // versions are equal } /** * Check if a version satisfies a range requirement */ satisfiesRange(version, range) { try { const rangePattern = /^([~^]?)(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.-]+))?$/; const match = range.match(rangePattern); if (!match) { throw new VersionError(`Invalid version range: ${range}`); } const operator = match[1] || ''; const requiredVersion = { major: parseInt(match[2], 10), minor: parseInt(match[3], 10), patch: parseInt(match[4], 10), prerelease: match[5] || undefined, }; switch (operator) { case '~': // Compatible within patch version return this.isCompatiblePatch(version, requiredVersion); case '^': // Compatible within minor version return this.isCompatibleMinor(version, requiredVersion); default: // Exact version match return this.compareVersions(version, requiredVersion) === 0; } } catch (error) { throw new VersionError(`Error checking version range: ${error}`); } } /** * Check compatibility between two versions */ checkCompatibility(current, required) { const compatible = this.isCompatible(current, required); const migrationRequired = !compatible && this.isMigrationPossible(current, required); const result = { compatible, requiredVersion: required, currentVersion: current, migrationRequired, }; if (migrationRequired) { result.migrationPath = this.generateMigrationPath(current, required); } return result; } /** * Increment version based on change type */ incrementVersion(currentVersion, changeType, prereleaseIdentifier) { const newVersion = { ...currentVersion }; switch (changeType) { case 'major': newVersion.major += 1; newVersion.minor = 0; newVersion.patch = 0; delete newVersion.prerelease; break; case 'minor': newVersion.minor += 1; newVersion.patch = 0; delete newVersion.prerelease; break; case 'patch': newVersion.patch += 1; delete newVersion.prerelease; break; case 'prerelease': if (!prereleaseIdentifier) { throw new VersionError('Prerelease identifier is required for prerelease version increment'); } newVersion.prerelease = prereleaseIdentifier; break; default: throw new VersionError(`Invalid change type: ${changeType}`); } return newVersion; } /** * Register a migration handler for a specific version transition */ registerMigrationHandler(fromVersion, toVersion, handler) { const key = `${fromVersion}->${toVersion}`; this.migrationHandlers.set(key, handler); } /** * Execute migration for a registry entry */ async migrateEntry(entry, targetVersion) { const currentVersionString = this.formatVersion(entry.version); const targetVersionString = this.formatVersion(targetVersion); const migrationKey = `${currentVersionString}->${targetVersionString}`; const handler = this.migrationHandlers.get(migrationKey); if (!handler) { throw new VersionError(`No migration handler found for ${migrationKey}`); } try { const migratedEntry = await handler(entry); migratedEntry.version = targetVersion; migratedEntry.updatedAt = new Date(); return migratedEntry; } catch (error) { throw new VersionError(`Migration failed from ${currentVersionString} to ${targetVersionString}: ${error}`); } } /** * Register custom compatibility rule */ registerCompatibilityRule(ruleKey, rule) { this.compatibilityRules.set(ruleKey, rule); } /** * Apply custom compatibility rule */ applyCompatibilityRule(ruleKey, v1, v2) { const rule = this.compatibilityRules.get(ruleKey); if (!rule) { throw new VersionError(`Compatibility rule '${ruleKey}' not found`); } return rule(v1, v2); } /** * Get the latest version from an array of versions */ getLatestVersion(versions) { if (versions.length === 0) { return null; } return versions.reduce((latest, current) => { return this.compareVersions(current, latest) > 0 ? current : latest; }); } /** * Filter versions by compatibility with a base version */ getCompatibleVersions(baseVersion, versions) { return versions.filter((version) => this.isCompatible(version, baseVersion)); } /** * Check if version is stable (no prerelease) */ isStableVersion(version) { return !version.prerelease; } /** * Check if version is prerelease */ isPrereleaseVersion(version) { return !!version.prerelease; } // Private helper methods setupDefaultCompatibilityRules() { // Backward compatibility rule this.compatibilityRules.set('backward', (current, required) => { return this.compareVersions(current, required) >= 0; }); // Strict compatibility rule this.compatibilityRules.set('strict', (current, required) => { return this.compareVersions(current, required) === 0; }); // Semantic compatibility rule this.compatibilityRules.set('semantic', (current, required) => { return this.isSemanticCompatible(current, required); }); } isCompatible(current, required) { // Apply semantic versioning compatibility rules return this.isSemanticCompatible(current, required); } isSemanticCompatible(current, required) { // Major version must match for compatibility if (current.major !== required.major) { return false; } // Current version must be greater than or equal to required return this.compareVersions(current, required) >= 0; } isCompatiblePatch(version, required) { return (version.major === required.major && version.minor === required.minor && version.patch >= required.patch); } isCompatibleMinor(version, required) { if (version.major !== required.major) { return false; } if (version.minor > required.minor) { return true; } if (version.minor === required.minor) { return version.patch >= required.patch; } return false; } isMigrationPossible(current, required) { // Migration is possible if versions are in the same major version line // or if there's a registered migration handler const currentVersionString = this.formatVersion(current); const requiredVersionString = this.formatVersion(required); const migrationKey = `${currentVersionString}->${requiredVersionString}`; return (this.migrationHandlers.has(migrationKey) || (current.major === required.major && this.compareVersions(current, required) < 0)); } generateMigrationPath(current, target) { const path = []; const currentVersionString = this.formatVersion(current); const targetVersionString = this.formatVersion(target); // Simple migration path - direct migration if possible if (this.migrationHandlers.has(`${currentVersionString}->${targetVersionString}`)) { path.push(`${currentVersionString}->${targetVersionString}`); } else { // Multi-step migration would require more complex logic path.push(`Complex migration required from ${currentVersionString} to ${targetVersionString}`); } return path; } } //# sourceMappingURL=VersionManager.js.map