@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
210 lines • 22.3 kB
JavaScript
;
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 });
exports.PackageCreationParams = void 0;
const ApexTypeFetcher_1 = __importDefault(require("../apex/parser/ApexTypeFetcher"));
const ProjectConfig_1 = __importDefault(require("../project/ProjectConfig"));
const SfpPackageContentGenerator_1 = __importDefault(require("./generators/SfpPackageContentGenerator"));
const SourceToMDAPIConvertor_1 = __importDefault(require("./packageFormatConvertors/SourceToMDAPIConvertor"));
const PackageManifest_1 = __importDefault(require("./components/PackageManifest"));
const MetadataCount_1 = __importDefault(require("./components/MetadataCount"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const fs = __importStar(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const SfpPackage_1 = __importStar(require("./SfpPackage"));
const AssignPermissionSetFetcher_1 = __importDefault(require("./propertyFetchers/AssignPermissionSetFetcher"));
const DestructiveManifestPathFetcher_1 = __importDefault(require("./propertyFetchers/DestructiveManifestPathFetcher"));
const ReconcileProfilePropertyFetcher_1 = __importDefault(require("./propertyFetchers/ReconcileProfilePropertyFetcher"));
const CreateUnlockedPackageImpl_1 = __importDefault(require("./packageCreators/CreateUnlockedPackageImpl"));
const CreateSourcePackageImpl_1 = __importDefault(require("./packageCreators/CreateSourcePackageImpl"));
const CreateDataPackageImpl_1 = __importDefault(require("./packageCreators/CreateDataPackageImpl"));
const lodash = require("lodash");
const PackageVersionUpdater_1 = __importDefault(require("./version/PackageVersionUpdater"));
const AnalyzerRegistry_1 = require("./analyser/AnalyzerRegistry");
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const CreateDiffPackageImpl_1 = __importDefault(require("./packageCreators/CreateDiffPackageImpl"));
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
class SfpPackageBuilder {
static async buildPackageFromProjectDirectory(logger, projectDirectory, sfdx_package, params, packageCreationParams, projectConfig) {
if (!projectConfig) {
projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(projectDirectory);
}
else {
// Clone the projectConfig to prevent mutation
projectConfig = lodash.cloneDeep(projectConfig);
}
let propertyFetchers = [
new AssignPermissionSetFetcher_1.default(),
new DestructiveManifestPathFetcher_1.default(),
new ReconcileProfilePropertyFetcher_1.default(),
];
let startTime = Date.now;
let sfpPackage = new SfpPackage_1.default();
sfpPackage.package_name = sfdx_package;
sfpPackage.projectConfig = projectConfig;
sfpPackage.apiVersion = sfpPackage.projectConfig.sourceApiVersion;
sfpPackage.packageDescriptor = ProjectConfig_1.default.getPackageDescriptorFromConfig(sfdx_package, sfpPackage.projectConfig);
sfpPackage.projectDirectory = projectDirectory ? projectDirectory : '';
sfpPackage.packageDirectory = sfpPackage.packageDescriptor.path;
//Set Default Version Number
sfpPackage.versionNumber = sfpPackage.packageDescriptor.versionNumber;
//set additional options
sfpPackage.sourceVersion = params?.sourceVersion;
sfpPackage.branch = params?.branch;
sfpPackage.repository_url = params?.repositoryUrl;
if (params?.configFilePath == null)
sfpPackage.configFilePath = 'config/project-scratch-def.json';
else
sfpPackage.configFilePath = params?.configFilePath;
for (const propertyFetcher of propertyFetchers) {
await propertyFetcher.getsfpProperties(sfpPackage, logger);
}
//Get Package Type
sfpPackage.package_type = ProjectConfig_1.default.getPackageType(projectConfig, sfdx_package);
sfpPackage = SfpPackageBuilder.handleVersionNumber(params, sfpPackage, packageCreationParams);
// Requires destructiveChangesPath which is set by the property fetcher
sfpPackage.workingDirectory = await SfpPackageContentGenerator_1.default.generateSfpPackageDirectory(logger, sfpPackage.projectDirectory, sfpPackage.projectConfig, sfpPackage.packageName, sfpPackage.packageDescriptor.path, sfpPackage.versionNumber, sfpPackage.destructiveChangesPath, sfpPackage.configFilePath, params?.pathToReplacementForceIgnore);
sfpPackage.resolvedPackageDirectory = path_1.default.join(sfpPackage.workingDirectory, sfpPackage.packageDescriptor.path);
//Don't proceed further if packageType is Data
if (sfpPackage.package_type != SfpPackage_1.PackageType.Data) {
let sourceToMdapiConvertor = new SourceToMDAPIConvertor_1.default(sfpPackage.workingDirectory, sfpPackage.packageDescriptor.path, ProjectConfig_1.default.getSFDXProjectConfig(sfpPackage.workingDirectory).sourceApiVersion, logger);
sfpPackage.mdapiDir = (await sourceToMdapiConvertor.convert()).packagePath;
const packageManifest = await PackageManifest_1.default.create(sfpPackage.mdapiDir);
sfpPackage.payload = packageManifest.manifestJson;
sfpPackage.triggers = packageManifest.fetchTriggers();
sfpPackage.isApexFound = packageManifest.isApexInPackage();
sfpPackage.isProfilesFound = packageManifest.isProfilesInPackage();
sfpPackage.isPermissionSetGroupFound = packageManifest.isPermissionSetGroupsFoundInPackage();
sfpPackage.isPayLoadContainTypesSupportedByProfiles = packageManifest.isPayLoadContainTypesSupportedByProfiles();
let apexFetcher = new ApexTypeFetcher_1.default(sfpPackage.resolvedPackageDirectory);
sfpPackage.apexClassesSortedByTypes = apexFetcher.getClassesClassifiedByType();
sfpPackage.apexTestClassses = apexFetcher.getTestClasses();
sfpPackage.metadataCount = await MetadataCount_1.default.getMetadataCount(sfpPackage.workingDirectory, sfpPackage.packageDescriptor.path);
sfpPackage.apexClassWithOutTestClasses = apexFetcher.getClassesOnlyExcludingTestsAndInterfaces();
sfpPackage.isTriggerAllTests = this.isAllTestsToBeTriggered(sfpPackage, logger);
//Load component Set
let componentSet = source_deploy_retrieve_1.ComponentSet.fromSource(path_1.default.resolve(sfpPackage.workingDirectory, sfpPackage.projectDirectory, sfpPackage.packageDirectory));
//Run through all analyzers
let analyzers = AnalyzerRegistry_1.AnalyzerRegistry.getAnalyzers();
for (const analyzer of analyzers) {
if (analyzer.isEnabled(sfpPackage, logger))
sfpPackage = await analyzer.analyze(sfpPackage, componentSet, logger);
}
}
//Create the actual package
let createPackage;
if (!packageCreationParams)
packageCreationParams = { breakBuildIfEmpty: true };
let packageType = sfpPackage.package_type;
if (params?.overridePackageTypeWith)
packageType = params?.overridePackageTypeWith.toLocaleLowerCase();
//Get Implementors
switch (packageType) {
case SfpPackage_1.PackageType.Unlocked:
createPackage = new CreateUnlockedPackageImpl_1.default(sfpPackage.workingDirectory, sfpPackage, packageCreationParams, logger, params);
break;
case SfpPackage_1.PackageType.Source:
createPackage = new CreateSourcePackageImpl_1.default(sfpPackage.workingDirectory, sfpPackage, packageCreationParams, logger, params);
break;
case SfpPackage_1.PackageType.Data:
createPackage = new CreateDataPackageImpl_1.default(sfpPackage.workingDirectory, sfpPackage, packageCreationParams, logger, params);
break;
case SfpPackage_1.PackageType.Diff:
packageCreationParams.revisionFrom = params.revisionFrom;
packageCreationParams.revisionTo = params.revisionTo;
createPackage = new CreateDiffPackageImpl_1.default(sfpPackage.workingDirectory, sfpPackage, packageCreationParams, logger, params);
break;
}
return createPackage.exec();
}
/*
* Handle version Numbers of package
* If VersionNumber is explcitly passed, use that
* else allow autosubstitute using buildNumber for Source and Data if available
*/
static handleVersionNumber(params, sfpPackage, packageCreationParams) {
if (params?.packageVersionNumber) {
sfpPackage.versionNumber = params.packageVersionNumber;
}
else if (packageCreationParams?.buildNumber) {
if (sfpPackage.packageType != SfpPackage_1.PackageType.Unlocked) {
let versionUpdater = new PackageVersionUpdater_1.default();
sfpPackage.versionNumber = versionUpdater.substituteBuildNumber(sfpPackage, packageCreationParams.buildNumber);
}
}
else {
sfpPackage.versionNumber = sfpPackage.packageDescriptor.versionNumber;
}
return sfpPackage;
}
static async buildPackageFromArtifact(artifact, logger) {
//Read artifact metadata
let sfpPackage = new SfpPackage_1.default();
Object.assign(sfpPackage, fs.readJSONSync(artifact.packageMetadataFilePath, { encoding: 'utf8' }));
sfpPackage.sourceDir = artifact.sourceDirectoryPath;
sfpPackage.changelogFilePath = artifact.changelogFilePath;
sfpPackage.projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(artifact.sourceDirectoryPath);
sfpPackage.packageDescriptor = ProjectConfig_1.default.getSFDXPackageDescriptor(artifact.sourceDirectoryPath, sfpPackage.package_name);
sfpPackage.projectDirectory = artifact.sourceDirectoryPath;
sfpPackage.packageDirectory = sfpPackage.packageDescriptor.path;
sfpPackage.isTriggerAllTests = this.isAllTestsToBeTriggered(sfpPackage, logger);
return sfpPackage;
}
static isAllTestsToBeTriggered(sfpPackage, logger) {
if (this.isOptimizedDeploymentForSourcePackage(sfpPackage) == false ||
(sfpPackage.packageType == SfpPackage_1.PackageType.Source &&
sfpPackage.isApexFound == true &&
sfpPackage.apexTestClassses == null)) {
sfp_logger_1.default.printHeaderLine('WARNING! NON OPTIMAL DEPLOYMENT', sfp_logger_2.COLOR_WARNING, sfp_logger_1.LoggerLevel.INFO, logger);
sfp_logger_1.default.log(`This package has apex classes/triggers, In order to deploy optimally, each class need to have a minimum` +
`75% test coverage,We are unable to find any test classes in the given package, hence will be deploying` +
`via triggering all local tests,This definitely is not optimal approach on large orgs` +
`Please consider adding test classes for the classes in the package`, sfp_logger_1.LoggerLevel.INFO, logger);
sfp_logger_1.default.printHeaderLine('', sfp_logger_2.COLOR_WARNING, sfp_logger_1.LoggerLevel.INFO, logger);
return true;
}
else
return false;
}
// Allow individual packages to use non optimized path
static isOptimizedDeploymentForSourcePackage(pkgDescriptor) {
if (pkgDescriptor['isOptimizedDeployment'] == null)
return true;
else
return pkgDescriptor['isOptimizedDeployment'];
}
}
exports.default = SfpPackageBuilder;
// Options while creating package
class PackageCreationParams {
constructor() {
this.breakBuildIfEmpty = true;
}
}
exports.PackageCreationParams = PackageCreationParams;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2ZwUGFja2FnZUJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29yZS9wYWNrYWdlL1NmcFBhY2thZ2VCdWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEscUZBQW1GO0FBQ25GLDZFQUFxRDtBQUNyRCx5R0FBaUY7QUFDakYsOEdBQXNGO0FBQ3RGLG1GQUEyRDtBQUMzRCwrRUFBdUQ7QUFDdkQsbUVBQXNFO0FBQ3RFLDZDQUErQjtBQUMvQixnREFBd0I7QUFFeEIsMkRBQThGO0FBRTlGLCtHQUF1RjtBQUN2Rix1SEFBK0Y7QUFDL0YseUhBQTBGO0FBQzFGLDRHQUFvRjtBQUNwRix3R0FBZ0Y7QUFDaEYsb0dBQTRFO0FBQzVFLGlDQUFrQztBQUVsQyw0RkFBb0U7QUFDcEUsa0VBQStEO0FBQy9ELCtFQUFrRTtBQUNsRSxvR0FBMkU7QUFDM0UscURBQXFEO0FBRXJELE1BQXFCLGlCQUFpQjtJQUMzQixNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxDQUNoRCxNQUFjLEVBQ2QsZ0JBQXdCLEVBQ3hCLFlBQW9CLEVBQ3BCLE1BQXlCLEVBQ3pCLHFCQUE2QyxFQUM3QyxhQUFtQjtRQUVuQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDakIsYUFBYSxHQUFHLHVCQUFhLENBQUMsb0JBQW9CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6RSxDQUFDO2FBQU0sQ0FBQztZQUNKLDhDQUE4QztZQUM5QyxhQUFhLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsSUFBSSxnQkFBZ0IsR0FBc0I7WUFDdEMsSUFBSSxvQ0FBMEIsRUFBRTtZQUNoQyxJQUFJLHdDQUE4QixFQUFFO1lBQ3BDLElBQUkseUNBQXdCLEVBQUU7U0FDakMsQ0FBQztRQUVGLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFH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