@voximplant/voxengine-ci
Version:
Manage Voximplant Platform `applications`, `rules` and `scenarios` from your own environment
354 lines (353 loc) • 20.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationModule = void 0;
const node_process_1 = require("node:process");
const vox_rule_service_1 = require("../domains/services/vox-rule.service");
const voximplant_context_1 = require("../domains/contexts/voximplant.context");
const log_message_generator_1 = require("../utils/log-message-generator");
const file_system_context_1 = require("../domains/contexts/file-system.context");
const vox_scenario_service_1 = require("../domains/services/vox-scenario.service");
const vox_application_service_1 = require("../domains/services/vox-application.service");
const application_config_service_1 = require("../domains/services/application-config.service");
const vox_rule_platform_repository_1 = require("../domains/repositories/vox-rule.platform.repository");
const vox_rule_persistent_repository_1 = require("../domains/repositories/vox-rule.persistent.repository");
const vox_scenario_platform_repository_1 = require("../domains/repositories/vox-scenario.platform.repository");
const vox_scenario_persistent_repository_1 = require("../domains/repositories/vox-scenario.persistent.repository");
const vox_application_platform_repository_1 = require("../domains/repositories/vox-application.platform.repository");
const vox_application_persistent_repository_1 = require("../domains/repositories/vox-application.persistent.repository");
class ApplicationModule {
constructor() {
this.lmg = log_message_generator_1.LogMessageGeneratorFactory.getInstance();
this.init = async () => {
try {
/**
* ApplicationConfigService
*/
const applicationConfigService = new application_config_service_1.ApplicationConfigService();
const applicationConfig = applicationConfigService.getConfig();
/**
* Configs
*/
const rootDirectoryName = applicationConfig.voxengine_ci.ROOT_DIRECTORY;
const metadataDirectoryName = '.voxengine-ci';
const voximplantCredentials = applicationConfig.voximplant.CREDENTIALS;
/**
* VoximplantContext
*/
const voximplantContext = new voximplant_context_1.VoximplantContext(voximplantCredentials);
await voximplantContext.init();
/**
* FileSystemContext
*/
const fileSystemContext = new file_system_context_1.FileSystemContext(rootDirectoryName, metadataDirectoryName);
await fileSystemContext.init();
/**
* VoxApplicationPlatformRepository
*/
const voxApplicationPlatformRepository = new vox_application_platform_repository_1.VoxApplicationPlatformRepository(voximplantContext);
voxApplicationPlatformRepository.init();
/**
* VoxRulePlatformRepository
*/
const voxRulePlatformRepository = new vox_rule_platform_repository_1.VoxRulePlatformRepository(voximplantContext);
voxRulePlatformRepository.init();
/**
* VoxScenarioPlatformRepository
*/
const voxScenarioPlatformRepository = new vox_scenario_platform_repository_1.VoxScenarioPlatformRepository(voximplantContext);
voxScenarioPlatformRepository.init();
/**
* VoxApplicationPersistentRepository
*/
const voxApplicationPersistentRepository = new vox_application_persistent_repository_1.VoxApplicationPersistentRepository(fileSystemContext);
await voxApplicationPersistentRepository.init();
/**
* VoxRulePersistentRepository
*/
const voxRulePersistentRepository = new vox_rule_persistent_repository_1.VoxRulePersistentRepository(fileSystemContext);
await voxRulePersistentRepository.init();
/**
* VoxScenarioPersistentRepository
*/
const voxScenarioPersistentRepository = new vox_scenario_persistent_repository_1.VoxScenarioPersistentRepository(fileSystemContext);
await voxScenarioPersistentRepository.init();
/**
* VoxApplicationService
*/
this.voxApplicationService = new vox_application_service_1.VoxApplicationService(voxApplicationPlatformRepository, voxApplicationPersistentRepository);
this.voxApplicationService.init();
/**
* VoxRuleService
*/
this.voxRuleService = new vox_rule_service_1.VoxRuleService(voxRulePlatformRepository, voxRulePersistentRepository);
this.voxRuleService.init();
/**
* VoxScenarioService
*/
this.voxScenarioService = new vox_scenario_service_1.VoxScenarioService(voxScenarioPlatformRepository, voxScenarioPersistentRepository);
this.voxScenarioService.init();
}
catch (error) {
console.error(this.lmg.generate('INIT_FAILED', this.constructor.name));
console.error(error);
(0, node_process_1.exit)(1);
}
};
this.projectCleanup = async () => {
try {
await this.voxApplicationService.cleanup();
await this.voxScenarioService.cleanup();
}
catch (error) {
console.error(this.lmg.generate('ERR__PROJECT_CLEANUP_FAILED', this.constructor.name));
console.error(error);
}
};
this.projectInit = async () => {
try {
const isApplicationAlreadyExists = await this.voxApplicationService.checkApplicationsAlreadyExists();
if (isApplicationAlreadyExists) {
throw new Error(this.lmg.generate('ERR__PROJECT_IS_ALREADY_INITIALIZED'));
}
const rawScenarios = await this.voxScenarioService.downloadScenarios();
this.voxScenarioService.checkScenariosNames(rawScenarios);
for (const { scenarioId } of rawScenarios) {
const rawFullScenario = await this.voxScenarioService.downloadScenario(scenarioId);
await this.voxScenarioService.saveScenario(rawFullScenario);
await this.voxScenarioService.saveScenarioMetadata(rawFullScenario);
}
const rawApplications = await this.voxApplicationService.downloadApplications();
if (!rawApplications.length) {
console.info(this.lmg.generate('INFO__NO_APPLICATIONS'));
return;
}
for (const rawApplication of rawApplications) {
await this.voxApplicationService.saveApplication(rawApplication);
await this.voxApplicationService.saveApplicationMetadata(rawApplication);
const rawRules = await this.voxRuleService.downloadApplicationRules(rawApplication);
await this.voxRuleService.saveRules(rawApplication, rawRules);
await this.voxRuleService.saveRulesMetadata(rawApplication, rawRules);
}
}
catch (error) {
console.error(this.lmg.generate('ERR__PROJECT_INIT_FAILED', this.constructor.name));
console.error(error);
}
};
this.getRulesByApplicationName = async (applicationName) => {
return ((await this.voxRuleService.readApplicationRulesByName(applicationName)) ??
[]);
};
this.getScenariosByRuleId = async (applicationName, applicationId, ruleId) => {
if (!ruleId)
return;
const rulesMetadataList = await this.voxRuleService.readApplicationRulesMetadata(applicationName);
const ruleMetadataById = rulesMetadataList?.find((ruleMetadata) => ruleMetadata.ruleId === ruleId);
const ruleList = await this.voxRuleService.readApplicationRulesByName(applicationName);
const ruleToUpload = ruleList?.find((rule) => rule.ruleName === ruleMetadataById?.ruleName);
if (!ruleToUpload) {
throw new Error(this.lmg.generate('ERR__RULE_ID_DOES_NOT_EXIST', ruleId.toString()));
}
const { scenarios, rulePattern } = ruleToUpload;
return {
scenarios,
rulePattern,
};
};
this.getScenariosByRuleName = async (applicationName, applicationId, ruleName) => {
if (!ruleName)
return;
const voxRulesList = await this.voxRuleService.readApplicationRulesByName(applicationName);
await this.voxScenarioService.cleanupDist();
const ruleByName = voxRulesList?.find((rule) => rule.ruleName === ruleName);
if (!ruleByName) {
throw new Error(this.lmg.generate('ERR__RULE_NAME_DOES_NOT_EXIST', ruleName));
}
const { scenarios, rulePattern } = ruleByName;
return { scenarios, rulePattern };
};
this.addApplicationToPlatform = async (applicationName) => {
try {
const applicationId = await this.voxApplicationService.addApplication(applicationName);
const rawApplication = {
applicationName,
applicationId: applicationId,
modified: new Date(),
secureRecordStorage: false,
};
await this.voxApplicationService.saveApplicationMetadata(rawApplication);
return applicationId;
}
catch (error) {
console.error(error);
throw new Error(this.lmg.generate('ERR__CANNOT_ADD_APP', applicationName));
}
};
this.bindScenarios = async (existingRule, uploadedScenariosInfo, applicationId, applicationName) => {
const uploadedScenariosIds = uploadedScenariosInfo.map(({ scenarioId }) => scenarioId);
const uploadedScenariosNames = uploadedScenariosInfo.map(({ scenarioName }) => scenarioName);
const bindScenarioRequest = {
scenarioId: uploadedScenariosIds,
scenarioName: uploadedScenariosNames.join(';'),
ruleId: existingRule.ruleId,
ruleName: existingRule.ruleName,
applicationId: applicationId,
applicationName,
bind: true,
};
const unbindScenarioRequest = {
scenarioId: existingRule.scenarios
// TODO: Nodejs mapper error (snake_case to camelCase)
// @ts-expect-error: Nodejs mapper error (snake_case to camelCase)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
.map(({ scenario_id }) => scenario_id)
.filter((scenarioId) => !uploadedScenariosIds.includes(scenarioId)),
scenarioName: existingRule.scenarios
// TODO: Nodejs mapper error (snake_case to camelCase)
// @ts-expect-error: Nodejs mapper error (snake_case to camelCase)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
.map(({ scenario_name }) => scenario_name)
.filter((scenarioName) => !uploadedScenariosNames.includes(scenarioName))
.join(';'),
ruleId: existingRule.ruleId,
ruleName: existingRule.ruleName,
applicationId: applicationId,
applicationName,
bind: false,
};
if (unbindScenarioRequest.scenarioId?.length) {
await this.voxScenarioService.addScenariosToRule(unbindScenarioRequest);
}
if (uploadedScenariosInfo.length) {
await this.voxScenarioService.addScenariosToRule(bindScenarioRequest);
}
};
this.applicationBuild = async (settings) => {
const { applicationName } = await this.voxApplicationService.getApplicationNameAndId(settings);
try {
const voxRulesList = await this.getRulesByApplicationName(applicationName);
await this.voxScenarioService.cleanupDist();
for (const voxRule of voxRulesList) {
const { scenarios } = voxRule;
await this.voxScenarioService.build(scenarios);
}
}
catch (error) {
console.error(this.lmg.generate('ERR__APPLICATION_BUILD_FAILED', this.constructor.name));
throw error;
}
};
this.applicationBuildAndUpload = async (settings) => {
try {
const getApplicationNameAndIdResult = await this.voxApplicationService.getApplicationNameAndId(settings);
const { applicationName } = getApplicationNameAndIdResult;
const applicationId = getApplicationNameAndIdResult.applicationId ??
(await this.addApplicationToPlatform(applicationName));
const voxRulesList = await this.getRulesByApplicationName(applicationName);
const rawApplication = {
applicationName,
applicationId,
modified: new Date(),
secureRecordStorage: false,
};
const rulesFromPlatform = await this.voxRuleService.downloadApplicationRules(rawApplication);
await this.voxScenarioService.cleanupDist();
for (const voxRule of voxRulesList) {
const { scenarios, rulePattern, ruleName } = voxRule;
await this.voxScenarioService.build(scenarios);
const { isForce } = settings;
await this.voxScenarioService.upload(scenarios, isForce);
const uploadedScenariosInfo = await this.voxScenarioService.getScenarioInfoFromPlatform(scenarios);
const existingRule = rulesFromPlatform?.find((rule) => rule.ruleName === ruleName);
if (!existingRule) {
await this.voxRuleService.uploadApplicationRule(applicationId, ruleName, uploadedScenariosInfo.map(({ scenarioId }) => scenarioId), rulePattern);
}
const rulePatternChanged = existingRule?.rulePattern !== rulePattern;
if (existingRule && rulePatternChanged) {
await this.voxRuleService.updateApplicationRule(rulePattern, existingRule.ruleId);
}
const scenariosChanged = existingRule?.scenarios
// TODO: Nodejs mapper error (snake_case to camelCase)
// @ts-expect-error: Nodejs mapper error (snake_case to camelCase)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
.map((scenario) => scenario.scenario_name)
.toString() !== scenarios.toString();
if (existingRule && scenariosChanged) {
await this.bindScenarios(existingRule, uploadedScenariosInfo, applicationId, applicationName);
}
}
const rawRulesWithOldOrder = await this.voxRuleService.downloadApplicationRules(rawApplication);
await this.voxRuleService.saveRulesMetadata(rawApplication, rawRulesWithOldOrder);
await this.voxRuleService.reorderRules(rawRulesWithOldOrder, voxRulesList);
const rawRules = await this.voxRuleService.downloadApplicationRules(rawApplication);
await this.voxRuleService.saveRulesMetadata(rawApplication, rawRules);
}
catch (error) {
console.error(this.lmg.generate('ERR__APPLICATION_BUILD_AND_UPLOAD_FAILED', this.constructor.name));
throw error;
}
};
this.applicationByRuleBuild = async (settings) => {
try {
const { applicationName, applicationId } = settings;
const fullApplicationName = await this.voxApplicationService.getApplicationFullName(applicationName);
const { scenarios } = (await this.getScenariosByRuleId(fullApplicationName, applicationId, settings.ruleId)) ??
(await this.getScenariosByRuleName(fullApplicationName, applicationId, settings.ruleName));
await this.voxScenarioService.build(scenarios);
}
catch (error) {
console.error(this.lmg.generate('ERR__APPLICATION_BY_RULE_BUILD_FAILED', this.constructor.name));
throw error;
}
};
this.applicationByRuleBuildAndUpload = async (settings) => {
try {
const { applicationName, applicationId } = await this.voxApplicationService.getApplicationNameAndId(settings);
const { isForce, ruleName, ruleId } = settings;
let newApplicationId;
if (!applicationId && !ruleId && !ruleName) {
newApplicationId = await this.addApplicationToPlatform(applicationName);
}
const { scenarios, rulePattern } = (await this.getScenariosByRuleId(applicationName, applicationId || newApplicationId, ruleId)) ||
(await this.getScenariosByRuleName(applicationName, applicationId || newApplicationId, ruleName));
await this.voxScenarioService.build(scenarios);
await this.voxScenarioService.upload(scenarios, isForce);
const uploadedScenariosInfo = await this.voxScenarioService.getScenarioInfoFromPlatform(scenarios);
const rawApplication = {
applicationName,
applicationId: applicationId || newApplicationId,
modified: new Date(),
secureRecordStorage: false,
};
const existingRule = (await this.voxRuleService.downloadApplicationRules(rawApplication))?.find((rule) => rule.ruleName === settings.ruleName ||
rule.ruleId === settings.ruleId);
if (settings.ruleId && !existingRule) {
throw new Error(this.lmg.generate('ERR__RULE_ID_DOES_NOT_EXIST', settings.ruleId.toString()));
}
if (!existingRule) {
await this.voxRuleService.uploadApplicationRule(applicationId || newApplicationId, settings.ruleName, uploadedScenariosInfo.map(({ scenarioId }) => scenarioId), rulePattern);
}
const rulePatternChanged = existingRule?.rulePattern !== rulePattern;
if (existingRule && rulePatternChanged) {
await this.voxRuleService.updateApplicationRule(rulePattern, existingRule.ruleId);
}
const scenariosChanged = existingRule?.scenarios
// TODO: Nodejs mapper error (snake_case to camelCase)
// @ts-expect-error: Nodejs mapper error (snake_case to camelCase)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
.map((scenario) => scenario.scenario_name)
.toString() !== scenarios.toString();
if (existingRule && scenariosChanged) {
await this.bindScenarios(existingRule, uploadedScenariosInfo, applicationId || newApplicationId, applicationName);
}
const rawRules = await this.voxRuleService.downloadApplicationRules(rawApplication);
await this.voxRuleService.saveRulesMetadata(rawApplication, rawRules);
}
catch (error) {
console.error(this.lmg.generate('ERR__APPLICATION_BY_RULE_BUILD_AND_UPLOAD_FAILED', this.constructor.name));
throw error;
}
};
}
}
exports.ApplicationModule = ApplicationModule;