UNPKG

@sap/modules-exploration

Version:

SAP Modules Exploration

164 lines (151 loc) 5.48 kB
import { getLogger } from "@log4js-node/log4js-api"; import { IChildLogger } from "@vscode-logging/types"; import * as fsExtra from "fs-extra"; import { IExplorationOptions } from "./ExplorationOptions"; import { IModuleFilter } from "@sap/consume-services-types"; import { messages } from "./i18n/messages"; import { IModuleInfo } from "./IModuleInfo"; import _ = require("lodash"); import path = require("path"); /** * Main module which exposes API to explore modules at runtime */ export class ModulesExploration { private static baseLogger: any = getLogger(ModulesExploration.name); private explorationOptions: IExplorationOptions; private generator: any; constructor(opts: IExplorationOptions, context: any, logger?: IChildLogger) { this.generator = _.get(context, "context.generator"); // Set defaults this.explorationOptions = { modulesPath: null, configPath: null, modulesFilter: null, // [filterField: "catalog",filterVal: ["V4"]}], }; _.assign(this.explorationOptions, opts); if (logger !== undefined) { ModulesExploration.baseLogger = logger.getChildLogger({ label: ModulesExploration.name, }); ModulesExploration.baseLogger.info( "Logger instance was received and updated." ); } } /** * Returns an array of explored modules metadata */ public async getExploredModules(): Promise<IModuleInfo[]> { // Filter module according to filters option return this._getFilteredModules(); } /** * Explores modules metadata and prompt them to the user using the given generator */ public async promptExploredModules(promptMsg?: string): Promise<string> { let selectedModule = ""; const message = promptMsg ? promptMsg : messages.getSelectModuleMessage(); const modulesList: IModuleInfo[] = this._getFilteredModules(); const modulesNameList = _.map(modulesList, "name"); if (_.size(modulesNameList) > 0) { const moduleTypePrompt = await this.generator.prompt([ { type: "list", name: "selectedModule", message, choices: modulesNameList, default: modulesNameList[0], }, ]); // Write selected module path to config file const moduleToRun = _.find(modulesList, (gen: any) => { return gen.name === moduleTypePrompt.selectedModule; }); if (moduleToRun) { selectedModule = path.join( this.explorationOptions.modulesPath, moduleToRun.type, moduleToRun.path ); } } return selectedModule; } private _getFilteredModules(): IModuleInfo[] { const modulesList: IModuleInfo[] = []; const modulesPath = this.explorationOptions.modulesPath; if (modulesPath && fsExtra.existsSync(modulesPath)) { fsExtra.readdirSync(modulesPath).forEach((moduleName: string) => { try { // For each module , read module.json file // eslint-disable-next-line @typescript-eslint/no-var-requires const modulesMetadata = require(path.join( modulesPath, moduleName, "modules.json" )); _.forIn( modulesMetadata, (value: any, modulesMetadataType: string) => { _.forEach( modulesMetadata[modulesMetadataType], (moduleMD: any) => { // In case module filter passed as null in options, add all modules if ( this.explorationOptions.modulesFilter === null || (moduleMD && this._passFilter(moduleMD)) ) { modulesList.push({ type: moduleName, name: moduleMD.name, path: moduleMD.path, entryPoint: moduleMD.entryPoint, }); } } ); } ); } catch (e) { const errorMsg = messages.getNoModuleFoundMessage(modulesPath, e); console.log(errorMsg); ModulesExploration.baseLogger.debug( this._getFilteredModules.name, // tslint:disable-next-line { modulesPath: modulesPath, status: "failed", error: errorMsg } ); } }); } return modulesList; } private _passFilter(moduleMetadata: any) { /*Filtering of modules is implemented as a "white list" model according to the definition below. A module will pass the defined filter when for all provided keys in the filter: * The module defines the filter key and the value provided by the filter is found also in the module * The module defines the filter key with empty value (meaning the module knows about the key existence but it is not relevant for it) */ const moduleFeatures: IModuleFilter[] = _.get( moduleMetadata, "features", {} ); let passes = true; _.forEach( this.explorationOptions.modulesFilter, (filter: IModuleFilter) => { _.forEach(moduleFeatures, (feature) => { if ( feature.name === filter.name && _.size(_.intersection(filter.value, feature.value)) === 0 ) { passes = false; } }); } ); // If all filter matches (true) then return true return passes; } }