UNPKG

@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
"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 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd0FjdGl2YXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3BhY2thZ2UvZGVwbG95bWVudEN1c3RvbWl6ZXJzL0Zsb3dBY3RpdmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtFQUE0RTtBQUU1RSxnRkFBd0Q7QUFDeEQsbUVBQXlGO0FBQ3pGLCtEQUF3SDtBQUN4SCw4Q0FBd0Q7QUFLeEQsaUVBQWlFO0FBRWpFLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUVuQyxNQUFxQixhQUFhO0lBQzlCLEtBQUssQ0FBQyxPQUFPLENBQ1QsVUFBc0IsRUFDdEIsWUFBMEIsRUFDMUIsTUFBYyxFQUNkLE1BQWMsRUFDZCxpQkFBb0M7UUFFcEMsSUFBSSxnQkFBZ0IsR0FBRyxZQUFZLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwRSxJQUFJLCtCQUErQixHQUFHLEVBQUUsQ0FBQztRQUN6QyxJQUFJLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLG9CQUFvQixHQUFHLEVBQUUsQ0FBQztRQUU5QixLQUFLLE1BQU0sZUFBZSxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDN0MsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxpQ0FBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3pELGFBQWE7Z0JBQ2Isc0NBQXNDO2dCQUN0QyxJQUFJLFVBQVUsR0FBRyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ2hELCtCQUErQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQzNDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ3RELENBQUM7cUJBQU0sQ0FBQztvQkFDSixvQkFBb0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUN4RCxDQUFDO1lBQ0wsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDRCxJQUFJLCtCQUErQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDbEQseURBQXlEO2dCQUMxRCx5RkFBeUY7Z0JBRW5GLElBQUksa0JBQWtCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNoQyxvQkFBUyxDQUFDLEdBQUcsQ0FDVCxnRkFBZ0Ysa0JBQWtCLEVBQUUsRUFDcEcsd0JBQVcsQ0FBQyxJQUFJLEVBQ2hCLE1BQU0sQ0FDVCxDQUFDO29CQUNGLE1BQU0sSUFBSSxDQUFDLDRCQUE0QixDQUFDLGtCQUFrQixFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDaEYsQ0FBQztnQkFDRCxJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDbEMsb0JBQVMsQ0FBQyxHQUFHLENBQ1QsMkZBQTJGLEVBQzNGLHdCQUFXLENBQUMsSUFBSSxFQUNoQixNQUFNLENBQ1QsQ0FBQztvQkFDRixNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUNwRSxDQUFDO1lBQ0wsQ0FBQztpQkFFRCxDQUFDO2dCQUNHLG9CQUFTLENBQUMsR0FBRyxDQUNULHNFQUFzRSxFQUN0RSx3QkFBVyxDQUFDLElBQUksRUFDaEIsTUFBTSxDQUNULENBQUM7WUFDTixDQUFDO1lBRUQsT0FBTztnQkFDSCxTQUFTLEVBQUUsUUFBUTtnQkFDbkIsTUFBTSxFQUFFLElBQUk7Z0JBQ1osT0FBTyxFQUFFLDZCQUE2QjthQUN6QyxDQUFDO1FBQ04sQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixvQkFBUyxDQUFDLEdBQUcsQ0FBQyw4Q0FBOEMsRUFBRSx3QkFBVyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztZQUN6RixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25CLG9CQUFTLENBQUMsR0FBRyxDQUFDLG1CQUFtQixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsd0JBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RSxDQUFDO0lBQ0wsQ0FBQztJQUNPLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxrQkFBNEIsRUFBRSxNQUFjLEVBQUUsTUFBYztRQUNuRyxLQUFLLE1BQU0sUUFBUSxJQUFJLGtCQUFrQixFQUFFLENBQUM7WUFDeEMsSUFBSSxLQUFLLEdBQUcseUxBQXlMLFFBQVEsR0FBRyxDQUFDO1lBRWpOLElBQUksQ0FBQztnQkFDRCxJQUFJLG9CQUFvQixHQUFHLE1BQU0scUJBQVcsQ0FBQyxLQUFLLENBQWlCLEtBQUssRUFBRSxNQUFNLENBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRXhHLEtBQUssTUFBTSxjQUFjLElBQUksb0JBQW9CLEVBQUUsQ0FBQztvQkFDaEQsSUFBSSxjQUFjLENBQUMsYUFBYSxJQUFJLElBQUksSUFBSSxjQUFjLENBQUMsYUFBYSxFQUFFLGFBQWEsR0FBRyxjQUFjLENBQUMsYUFBYSxFQUFFLGFBQWEsRUFBRSxDQUFDO3dCQUNwSSxJQUFJLENBQUM7NEJBQ0QsTUFBTSxJQUFBLHlCQUFRLEVBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxDQUFDOzRCQUN2QyxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUEsOEJBQWlCLEVBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyx1Q0FBdUMsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQzt3QkFDNUksQ0FBQzt3QkFBQyxPQUFPLGVBQWUsRUFBRSxDQUFDOzRCQUN2QixvQkFBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsY0FBYyxDQUFDLGFBQWEsS0FBSyxlQUFlLEVBQUUsRUFBRSx3QkFBVyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQzt3QkFDMUgsQ0FBQztvQkFDTCxDQUFDO3lCQUFNLENBQUM7d0JBQ0osb0JBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFBLDhCQUFpQixFQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsMERBQTBELEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7b0JBQy9KLENBQUM7Z0JBQ0wsQ0FBQztZQUNMLENBQUM7WUFBQyxPQUFPLFVBQVUsRUFBRSxDQUFDO2dCQUNsQixvQkFBUyxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsUUFBUSxNQUFNLFVBQVUsRUFBRSxFQUFFLHdCQUFXLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ2hILENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQUMsb0JBQThCLEVBQUUsTUFBYyxFQUFFLE1BQWM7UUFDdkYsS0FBSyxNQUFNLElBQUksSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQztnQkFDRCxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUEsa0NBQWlCLEVBQzFDO29CQUNJLGFBQWEsRUFBRSxJQUFJO29CQUNuQixlQUFlLEVBQUUsRUFBRTtpQkFDdEIsRUFDRCxNQUFNLENBQ1QsQ0FBQztnQkFFRixNQUFNLElBQUEsMkJBQVUsRUFBQyxjQUFjLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ3pDLG9CQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBQSw4QkFBaUIsRUFBQyxJQUFJLENBQUMsK0NBQStDLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDNUgsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2Isb0JBQVMsQ0FBQyxHQUFHLENBQUMsMkJBQTJCLElBQUkseUJBQXlCLEVBQUUsd0JBQVcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ25HLG9CQUFTLENBQUMsR0FBRyxDQUFDLG1CQUFtQixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsd0JBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RSxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsU0FBUyxDQUFDLFVBQXNCLEVBQUUsSUFBd0IsRUFBRSxNQUFjO1FBQ25GLElBQUcsVUFBVSxDQUFDLGlCQUFpQixDQUFDLFlBQVksSUFBSSx3QkFBVyxDQUFDLElBQUk7WUFDNUQsT0FBTyxLQUFLLENBQUM7UUFDakIsSUFDSSxVQUFVLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLElBQUksU0FBUztZQUM5RCxVQUFVLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLElBQUksSUFBSSxFQUMzRCxDQUFDO1lBQ0MsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFRCw0QkFBNEIsQ0FDeEIsVUFBc0IsRUFDdEIsWUFBMEIsRUFDMUIsSUFBd0IsRUFDeEIsTUFBYztRQUVkLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBQ0Qsb0JBQW9CLENBQUMsVUFBa0IsRUFBRSxRQUFnQixFQUFFLFVBQWtCO1FBQ3pFLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRU0sT0FBTztRQUNWLE9BQU8sZ0JBQWdCLENBQUM7SUFDNUIsQ0FBQztJQUVPLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQywrQkFBeUMsRUFBRSxNQUFjLEVBQUUsTUFBYztRQUM1RyxJQUFJLENBQUM7WUFDRCx3REFBd0Q7WUFDeEQsb0JBQVMsQ0FBQyxHQUFHLENBQUMsb0NBQW9DLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFFOUUsSUFBSSxLQUFLLEdBQUcsMEVBQTBFLENBQUM7WUFDdkYsSUFBSSwwQkFBMEIsR0FBRyxLQUFLLENBQUM7WUFFdkMsSUFBSSxpQkFBaUIsR0FBRyxNQUFNLHFCQUFXLENBQUMsS0FBSyxDQUFPLEtBQUssRUFBRSxNQUFNLENBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDM0YsSUFBSSxTQUFTLEdBQUcsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDckQsSUFBSSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUM7Z0JBQ2xCLElBQUksRUFBRSxTQUFTO2dCQUNmLEtBQUssRUFBRSxrQ0FBaUI7YUFDM0IsQ0FBQyxDQUFDO1lBQ0gsS0FBSyxNQUFNLFdBQVcsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLENBQUM7b0JBQ0QsSUFDSSxXQUFXLENBQUMsV0FBVyxJQUFJLEVBQUU7d0JBQzdCLCtCQUErQixDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLEVBQ25FLENBQUM7d0JBQ0MsMEJBQTBCLEdBQUcsSUFBSSxDQUFDO3dCQUNsQyxvQkFBUyxDQUFDLEdBQUcsQ0FDVCxRQUFRLFdBQVcsQ0FBQyxXQUFXLFFBQVEsV0FBVyxDQUFDLFdBQVcseUNBQXlDLEVBQ3ZHLHdCQUFXLENBQUMsSUFBSSxFQUNoQixNQUFNLENBQ1QsQ0FBQzt3QkFDRixJQUFJLEtBQUssR0FBRyxNQUFNLHFCQUFXLENBQUMsS0FBSyxDQUMvQixrRkFBa0YsV0FBVyxDQUFDLFdBQVcsK0JBQStCLEVBQ3hJLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFDdEIsSUFBSSxDQUNQLENBQUM7d0JBQ0YsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDcEMsTUFBTSxJQUFBLDRCQUFXLEVBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQzt3QkFDakQsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7b0JBQ3hGLENBQUM7Z0JBQ0wsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNiLG9CQUFTLENBQUMsR0FBRyxDQUNULHFDQUFxQyxXQUFXLENBQUMsV0FBVyxZQUFZLEVBQ3hFLHdCQUFXLENBQUMsS0FBSyxFQUNqQixNQUFNLENBQ1QsQ0FBQztvQkFDRixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFLDJCQUEyQixDQUFDLENBQUMsQ0FBQztvQkFDNUYsb0JBQVMsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSx3QkFBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN2RSxDQUFDO1lBQ0wsQ0FBQztZQUNELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksMEJBQTBCLEVBQUUsQ0FBQztnQkFDakQsb0JBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDcEMsQ0FBQztpQkFBTSxDQUFDO2dCQUNKLG9CQUFTLENBQUMsR0FBRyxDQUNULCtFQUErRSxFQUMvRSx3QkFBVyxDQUFDLElBQUksRUFDaEIsTUFBTSxDQUNULENBQUM7WUFDTixDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixvQkFBUyxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsRUFBRSx3QkFBVyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1RSxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLHdCQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkUsQ0FBQztJQUNMLENBQUM7Q0FDSjtBQXpNRCxnQ0F5TUMifQ==