UNPKG

@flxbl-io/sfp

Version:

sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model

235 lines 25.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ProjectConfig_1 = __importDefault(require("../../project/ProjectConfig")); const sfp_logger_1 = require("@flxbl-io/sfp-logger"); const sfp_logger_2 = __importStar(require("@flxbl-io/sfp-logger")); const lodash_1 = __importDefault(require("lodash")); const UserDefinedExternalDependency_1 = __importDefault(require("../../project/UserDefinedExternalDependency")); const semver_1 = __importDefault(require("semver")); class TransitiveDependencyResolver { constructor(sfdxProjectConfig, logger) { this.sfdxProjectConfig = sfdxProjectConfig; this.logger = logger; } async resolveTransitiveDependencies() { const result = await this.resolveTransitiveDependenciesWithDetails(); return result.resolvedDependencies; } async resolveTransitiveDependenciesWithDetails() { sfp_logger_2.default.log('Validating Project Dependencies...', sfp_logger_2.LoggerLevel.INFO, this.logger); let clonedProjectConfig = await lodash_1.default.cloneDeep(this.sfdxProjectConfig); clonedProjectConfig = await new UserDefinedExternalDependency_1.default().cleanupEntries(clonedProjectConfig); let pkgWithDependencies = ProjectConfig_1.default.getAllPackagesAndItsDependencies(clonedProjectConfig); pkgWithDependencies = this.fillDepsWithUserDefinedExternalDependencyMap(pkgWithDependencies, new UserDefinedExternalDependency_1.default().fetchDependencyEntries(clonedProjectConfig)); // Track version contributors during resolution const versionContributors = new Map(); const originalDeps = new Map(pkgWithDependencies); pkgWithDependencies = this.fillDepsTransitively(pkgWithDependencies, versionContributors); let sortedPackages = this.topologicalSort(pkgWithDependencies); let sortedPkgWithDependencies = new Map(); sortedPackages.forEach(pkg => { let dependencies = pkgWithDependencies.get(pkg) || []; let uniqueDependencies = new Map(); dependencies.forEach(dep => { const existing = uniqueDependencies.get(dep.package); if (!existing || this.compareVersions(dep.versionNumber, existing.versionNumber) > 0) { uniqueDependencies.set(dep.package, dep); } }); let sortedDependencies = Array.from(uniqueDependencies.values()) .sort((a, b) => sortedPackages.indexOf(a.package) - sortedPackages.indexOf(b.package)); sortedPkgWithDependencies.set(pkg, sortedDependencies); }); // Generate and log dependency details const details = this.generateDependencyDetails(sortedPackages, sortedPkgWithDependencies, originalDeps, versionContributors); return { resolvedDependencies: sortedPkgWithDependencies, details }; } compareVersions(version1, version2) { if (!version1 && !version2) return 0; if (!version1) return -1; if (!version2) return 1; // Handle LATEST/NEXT suffixes const v1HasLatest = version1.endsWith('.LATEST'); const v2HasLatest = version2.endsWith('.LATEST'); const v1HasNext = version1.endsWith('.NEXT'); const v2HasNext = version2.endsWith('.NEXT'); // If one has LATEST and other doesn't, LATEST wins if ((v1HasLatest || v1HasNext) && !v2HasLatest && !v2HasNext) return 1; if ((v2HasLatest || v2HasNext) && !v1HasLatest && !v1HasNext) return -1; // Extract base version (removing LATEST/NEXT if present) const v1Base = version1.replace(/\.(LATEST|NEXT)$/, ''); const v2Base = version2.replace(/\.(LATEST|NEXT)$/, ''); // Split into version parts const v1Parts = v1Base.split('.'); const v2Parts = v2Base.split('.'); // Compare first three parts using semver const v1Semver = v1Parts.slice(0, 3).join('.'); const v2Semver = v2Parts.slice(0, 3).join('.'); const semverCompare = semver_1.default.compare(semver_1.default.coerce(v1Semver) || '0.0.0', semver_1.default.coerce(v2Semver) || '0.0.0'); if (semverCompare !== 0) return semverCompare; // If semver parts are equal, compare build numbers (4th part) const buildNum1 = parseInt(v1Parts[3] || '0'); const buildNum2 = parseInt(v2Parts[3] || '0'); return buildNum1 - buildNum2; } fillDepsWithUserDefinedExternalDependencyMap(pkgWithDependencies, externalDependencyMap) { if (externalDependencyMap) { for (let pkg of Object.keys(externalDependencyMap)) { pkgWithDependencies.set(pkg, externalDependencyMap[pkg]); } } return pkgWithDependencies; } generateDependencyDetails(sortedPackages, resolvedDeps, originalDeps, versionContributors) { const details = new Map(); sortedPackages.forEach(pkg => { const dependencies = resolvedDeps.get(pkg) || []; if (dependencies.length > 0) { sfp_logger_2.default.log((0, sfp_logger_1.COLOR_HEADER)(`\nPackage: ${pkg}`), sfp_logger_2.LoggerLevel.INFO, this.logger); sfp_logger_2.default.log((0, sfp_logger_1.COLOR_HEADER)('----------------------------------------'), sfp_logger_2.LoggerLevel.INFO, this.logger); sfp_logger_2.default.log((0, sfp_logger_1.COLOR_HEADER)('Dependencies:'), sfp_logger_2.LoggerLevel.INFO, this.logger); const pkgDetails = {}; dependencies.forEach(dep => { const isDirect = originalDeps.get(pkg)?.some(d => d.package === dep.package && d.versionNumber === dep.versionNumber) || false; const contributorsSet = versionContributors.get(dep.package)?.get(dep.versionNumber || '') || new Set(); const contributors = Array.from(contributorsSet); let message = `${dep.package}@${dep.versionNumber || 'unknown'}`; if (isDirect) { message += ' (direct dependency)'; } else if (contributors.length > 0) { message += ` (via ${contributors.join(', ')})`; } sfp_logger_2.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(` ${message}`), sfp_logger_2.LoggerLevel.INFO, this.logger); pkgDetails[dep.package] = { version: dep.versionNumber || 'unknown', isDirect, contributors }; }); details.set(pkg, pkgDetails); } }); return details; } fillDepsTransitively(pkgWithDependencies, versionContributors) { let dependencyMap = new Map(pkgWithDependencies); const resolveDependencies = (pkg, chain = new Set()) => { sfp_logger_2.default.log((0, sfp_logger_1.COLOR_HEADER)(`fetching dependencies for package:`) + (0, sfp_logger_1.COLOR_KEY_MESSAGE)(pkg), sfp_logger_2.LoggerLevel.TRACE, this.logger); if (chain.has(pkg)) { const circularChain = Array.from(chain).join(' -> '); const errorMessage = `Circular dependency detected: ${circularChain} -> ${pkg}. Salesforce does not support circular dependencies between packages.`; sfp_logger_2.default.log((0, sfp_logger_1.COLOR_ERROR)(errorMessage), sfp_logger_2.LoggerLevel.ERROR, this.logger); throw new Error(errorMessage); } chain.add(pkg); let dependencies = dependencyMap.get(pkg) || []; let allDependencies = new Map(); // Add direct dependencies dependencies.forEach(dep => { const existing = allDependencies.get(dep.package); if (!existing || this.compareVersions(dep.versionNumber, existing.versionNumber) > 0) { allDependencies.set(dep.package, dep); // Track version contributor if (!versionContributors.has(dep.package)) { versionContributors.set(dep.package, new Map()); } const packageVersions = versionContributors.get(dep.package); if (!packageVersions.has(dep.versionNumber || '')) { packageVersions.set(dep.versionNumber || '', new Set()); } packageVersions.get(dep.versionNumber || '').add(pkg); } }); // Add transitive dependencies dependencies.forEach(dep => { if (dependencyMap.has(dep.package)) { let transitiveDeps = resolveDependencies(dep.package, new Set(chain)); transitiveDeps.forEach(td => { const existing = allDependencies.get(td.package); if (!existing || this.compareVersions(td.versionNumber, existing.versionNumber) > 0) { allDependencies.set(td.package, td); // Track version contributor if (!versionContributors.has(td.package)) { versionContributors.set(td.package, new Map()); } const packageVersions = versionContributors.get(td.package); if (!packageVersions.has(td.versionNumber || '')) { packageVersions.set(td.versionNumber || '', new Set()); } packageVersions.get(td.versionNumber || '').add(dep.package); } }); } }); chain.delete(pkg); return Array.from(allDependencies.values()); }; for (let pkg of dependencyMap.keys()) { let resolvedDeps = resolveDependencies(pkg); dependencyMap.set(pkg, resolvedDeps); } return dependencyMap; } swapAndDropArrayElement(arr, i, j) { if (i < 0 || i >= arr.length || j < 0 || j >= arr.length) { return arr; } let newArr = [...arr]; [newArr[i], newArr[j]] = [newArr[j], newArr[i]]; return [...newArr.slice(0, j), ...newArr.slice(j + 1)]; } topologicalSort(pkgWithDependencies) { let visited = new Set(); let result = []; const visit = (pkg) => { if (!visited.has(pkg)) { visited.add(pkg); let dependencies = pkgWithDependencies.get(pkg) || []; dependencies.forEach(dep => visit(dep.package)); result.push(pkg); } }; for (let pkg of pkgWithDependencies.keys()) { visit(pkg); } return result; } } exports.default = TransitiveDependencyResolver; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhbnNpdGl2ZURlcGVuZGVuY3lSZXNvbHZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3BhY2thZ2UvZGVwZW5kZW5jaWVzL1RyYW5zaXRpdmVEZXBlbmRlbmN5UmVzb2x2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdGQUF3RDtBQUN4RCxxREFBbUc7QUFDbkcsbUVBQXNFO0FBQ3RFLG9EQUF1QjtBQUN2QixnSEFBMkY7QUFDM0Ysb0RBQTRCO0FBYTVCLE1BQXFCLDRCQUE0QjtJQUM3QyxZQUFvQixpQkFBc0IsRUFBVSxNQUFlO1FBQS9DLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBSztRQUFVLFdBQU0sR0FBTixNQUFNLENBQVM7SUFBRyxDQUFDO0lBRWhFLEtBQUssQ0FBQyw2QkFBNkI7UUFDdEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsd0NBQXdDLEVBQUUsQ0FBQztRQUNyRSxPQUFPLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztJQUN2QyxDQUFDO0lBRU0sS0FBSyxDQUFDLHdDQUF3QztRQUNqRCxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbkYsSUFBSSxtQkFBbUIsR0FBRyxNQUFNLGdCQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3BFLG1CQUFtQixHQUFHLE1BQU0sSUFBSSx1Q0FBZ0MsRUFBRSxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3ZHLElBQUksbUJBQW1CLEdBQUcsdUJBQWEsQ0FBQyxnQ0FBZ0MsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQzlGLG1CQUFtQixHQUFHLElBQUksQ0FBQyw0Q0FBNEMsQ0FDbkUsbUJBQW1CLEVBQ25CLElBQUksdUNB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