@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
187 lines • 18.9 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 });
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const QueryHelper_1 = __importDefault(require("../../queryHelper/QueryHelper"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const FlowOperations_1 = require("../../flows/FlowOperations");
const SfpPackage_1 = require("../SfpPackage");
const TableConstants_1 = require("../../display/TableConstants");
const Table = require('cli-table');
class FlowActivator {
async execute(sfpPackage, componentSet, sfpOrg, logger, deploymentContext) {
let sourceComponents = componentSet.getSourceComponents().toArray();
let masterLabelsOfAllFlowsInPackage = [];
let flowsToBeActivated = [];
let flowsToBeDeactivated = [];
for (const sourceComponent of sourceComponents) {
if (sourceComponent.type.name === source_deploy_retrieve_1.registry.types.flow.name) {
//Parse Flows
//Determining the flow to be activated
let flowAsJSON = sourceComponent.parseXmlSync();
masterLabelsOfAllFlowsInPackage.push(flowAsJSON['Flow']['label']);
if (flowAsJSON['Flow']['status'] == 'Active') {
flowsToBeActivated.push(sourceComponent.fullName);
}
else {
flowsToBeDeactivated.push(sourceComponent.fullName);
}
}
}
try {
if (masterLabelsOfAllFlowsInPackage.length > 0) {
// Need to move this to a seperate pre deployment process
// await this.cleanupOldestFlowVersion(masterLabelsOfAllFlowsInPackage, sfpOrg, logger);
if (flowsToBeActivated.length > 0) {
sfp_logger_1.default.log(`Active flows found in the package, attempting to activate latest versions of ${flowsToBeActivated}`, sfp_logger_1.LoggerLevel.INFO, logger);
await this.activateLatestVersionOfFlows(flowsToBeActivated, sfpOrg, logger);
}
if (flowsToBeDeactivated.length > 0) {
sfp_logger_1.default.log(`Obsolete/Draft/InvalidDraft flows found in the package, attempting to inactivate the flow`, sfp_logger_1.LoggerLevel.INFO, logger);
await this.deactivateFlow(flowsToBeDeactivated, sfpOrg, logger);
}
}
else {
sfp_logger_1.default.log(`No flows found in the package, skipping flow activation/deactivation`, sfp_logger_1.LoggerLevel.INFO, logger);
}
return {
deploy_id: `000000`,
result: true,
message: `Activated/Inactivated Flows`,
};
}
catch (error) {
sfp_logger_1.default.log(`Unable to activate flow, skipping activation`, sfp_logger_1.LoggerLevel.ERROR, logger);
console.log(error);
sfp_logger_1.default.log(`Error Details : ${error.stack}`, sfp_logger_1.LoggerLevel.TRACE);
}
}
async activateLatestVersionOfFlows(flowsToBeActivated, sfpOrg, logger) {
for (const flowName of flowsToBeActivated) {
let query = `SELECT Id, DeveloperName, ActiveVersion.FullName, ActiveVersion.VersionNumber, NamespacePrefix,LatestVersion.VersionNumber,LatestVersionId FROM FlowDefinition WHERE DeveloperName = '${flowName}'`;
try {
let flowDefinitionsInOrg = await QueryHelper_1.default.query(query, sfpOrg.getConnection(), true);
for (const flowDefinition of flowDefinitionsInOrg) {
if (flowDefinition.ActiveVersion == null || flowDefinition.LatestVersion?.VersionNumber > flowDefinition.ActiveVersion?.VersionNumber) {
try {
await (0, FlowOperations_1.activate)(flowDefinition, sfpOrg);
sfp_logger_1.default.log(`Flow ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(flowDefinition.DeveloperName)} is activated in the org successfully`, sfp_logger_1.LoggerLevel.INFO, logger);
}
catch (activationError) {
sfp_logger_1.default.log(`Error activating flow ${flowDefinition.DeveloperName}: ${activationError}`, sfp_logger_1.LoggerLevel.ERROR, logger);
}
}
else {
sfp_logger_1.default.log(`Flow ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(flowDefinition.DeveloperName)}'s latest version is already active, skipping activation`, sfp_logger_1.LoggerLevel.INFO, logger);
}
}
}
catch (queryError) {
sfp_logger_1.default.log(`Error querying flow definition for '${flowName}': ${queryError}`, sfp_logger_1.LoggerLevel.ERROR, logger);
}
}
}
async deactivateFlow(flowsToBeDeactivated, sfpOrg, logger) {
for (const flow of flowsToBeDeactivated) {
try {
const flowdefinition = await (0, FlowOperations_1.getFlowDefinition)({
developername: flow,
namespaceprefix: '',
}, sfpOrg);
await (0, FlowOperations_1.deactivate)(flowdefinition, sfpOrg);
sfp_logger_1.default.log(`Flow ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(flow)} is marked as inactive in the org sucessfully`, sfp_logger_1.LoggerLevel.INFO, logger);
}
catch (error) {
sfp_logger_1.default.log(`Unable to deactive flow ${flow}, skipping deactivation`, sfp_logger_1.LoggerLevel.ERROR, logger);
sfp_logger_1.default.log(`Error Details : ${error.stack}`, sfp_logger_1.LoggerLevel.TRACE);
}
}
}
async isEnabled(sfpPackage, conn, logger) {
if (sfpPackage.packageDescriptor.package_type == SfpPackage_1.PackageType.Data)
return false;
if (sfpPackage.packageDescriptor.enableFlowActivation == undefined ||
sfpPackage.packageDescriptor.enableFlowActivation == true) {
return true;
}
return false;
}
gatherComponentsToBeDeployed(sfpPackage, componentSet, conn, logger) {
throw new Error('Method not implemented.');
}
getDeploymentOptions(target_org, waitTime, apiVersion) {
throw new Error('Method not implemented.');
}
getName() {
return 'Flow Activator';
}
async cleanupOldestFlowVersion(masterLabelsOfAllFlowsInPackage, sfpOrg, logger) {
try {
//count flow versions of each flow definition in the org
sfp_logger_1.default.log(`Checking current versions of flows`, sfp_logger_1.LoggerLevel.INFO, logger);
let query = `SELECT MasterLabel, COUNT(id) RecordCount FROM Flow GROUP BY MasterLabel`;
let isFlowVersionPurgeDetected = false;
let flowVersionsInOrg = await QueryHelper_1.default.query(query, sfpOrg.getConnection(), true);
let tableHead = ['Flow', 'Versions Count', 'Action'];
let table = new Table({
head: tableHead,
chars: TableConstants_1.ZERO_BORDER_TABLE,
});
for (const flowVersion of flowVersionsInOrg) {
try {
if (flowVersion.RecordCount == 50 &&
masterLabelsOfAllFlowsInPackage.includes(flowVersion.MasterLabel)) {
isFlowVersionPurgeDetected = true;
sfp_logger_1.default.log(`Flow ${flowVersion.MasterLabel} has ${flowVersion.RecordCount} versions, deleting the oldest versions`, sfp_logger_1.LoggerLevel.INFO, logger);
let flows = await QueryHelper_1.default.query(`SELECT Id, VersionNumber, FullName, MasterLabel FROM Flow WHERE MasterLabel = '${flowVersion.MasterLabel}' ORDER BY VersionNumber DESC`, sfpOrg.getConnection(), true);
let flowsToDelete = flows.slice(49);
await (0, FlowOperations_1.deleteFlows)(flowsToDelete, sfpOrg, logger);
table.push([flowVersion.MasterLabel, flowVersion.RecordCount, 'Deleted 1 version']);
}
}
catch (error) {
sfp_logger_1.default.log(`Unable to purge flow versions for ${flowVersion.MasterLabel}, skipping`, sfp_logger_1.LoggerLevel.ERROR, logger);
table.push([flowVersion.MasterLabel, flowVersion.RecordCount, 'Unable to delete versions']);
sfp_logger_1.default.log(`Error Details : ${error.stack}`, sfp_logger_1.LoggerLevel.TRACE);
}
}
if (table.length > 1 && isFlowVersionPurgeDetected) {
sfp_logger_1.default.log(table.toString());
}
else {
sfp_logger_1.default.log(`All flows in the package have less than 50 versions, skipping version cleanup`, sfp_logger_1.LoggerLevel.INFO, logger);
}
}
catch (error) {
sfp_logger_1.default.log(`Unable to cleanup flow versions`, sfp_logger_1.LoggerLevel.ERROR, logger);
sfp_logger_1.default.log(`Error Details : ${error.stack}`, sfp_logger_1.LoggerLevel.TRACE);
}
}
}
exports.default = FlowActivator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd0FjdGl2YXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3BhY2thZ2UvZGVwbG95bWVudEN1c3RvbWl6ZXJzL0Zsb3dBY3RpdmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtFQUE0RTtBQUU1RSxnRkFBd0Q7QUFDeEQsbUVBQXlGO0FBQ3pGLCtEQUF3SDtBQUN4SCw4Q0FBd0Q7QUFLeEQsaUVBQWlFO0FBRWpFLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUVuQyxNQUFxQixhQUFhO0lBQzlCLEtBQUssQ0FBQyxPQUFPLENBQ1QsVUFBc0IsRUFDdEIsWUFBMEIsRUFDMUIsTUFBYyxFQUNkLE1BQWMsRUFDZCxpQkFBb0M7UUFFcEMsSUFBSSxnQkFBZ0IsR0FBRyxZQUFZLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwRSxJQUFJLCtCQUErQixHQUFHLEVBQUUsQ0FBQztRQUN6QyxJQUFJLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLG9CQUFvQixHQUFHLEVBQUUsQ0FBQztRQUU5QixLQUFLLE1BQU0sZUFBZSxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDN0MsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxpQ0FBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3pELGFBQWE7Z0JBQ2Isc0NBQXNDO2dCQUN0QyxJQUFJLFVBQVUsR0FBRyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ2hELCtCQUErQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksUUFB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