/** * @author Martin Karkowski * @email m.karkowski@zema.de * @create date 2020-11-11 14:19:10 * @modify date 2020-12-02 17:05:41 * @desc [description] */ import { readFile } from "fs/promises"; import { join, resolve } from "path"; import "reflect-metadata"; import { createFile, listFiles } from "../helpers/fileMethods"; import { getNopeLogger } from "../logger/getLogger"; import { IInstanceCreationMsg } from "../types/nope/nopeCommunication.interface"; import { IPackageDescription } from "../types/nope/nopePackage.interface"; import { INopePackageLoader } from "../types/nope/nopePackageLoader.interface"; export interface IPackageConfig { nameOfPackage: string; defaultInstances: { options: Partial; selector: string | symbol; }[]; autostart: { [index: string]: { delay?: number; params: any[]; }[]; }; // File Path of the element. path: string; } export interface IConfigFile { functions: { path: string; functions: []; }[]; packages: IPackageConfig[]; } /** * List the available Packages * * @export * @param {string} [dir='./modules'] * @return {*} */ export async function listPackages(dir = "./modules") { // Define the Return Array. const ret = new Array<{ package: IPackageDescription; path: string; }>(); // Scan for the Package-Files // And iterate over them. for (const fileName of await listFiles(dir, ".package.js")) { // Now Try to load a Package, to test whether is is an assembly. try { ret.push({ package: (await import(resolve(fileName))) .DESCRIPTION as IPackageDescription, path: fileName }); } catch (e) { getNopeLogger("helper-list-packages").error( "Failed Loading the Package " + fileName ); getNopeLogger("helper-list-packages").error(e); } } return ret; } export async function listFunctions(dir = "./modules") { // Define the Return Array. const ret = new Array<{ content: any; path: string; }>(); // Scan for the Package-Files // And iterate over them. for (const fileName of await listFiles(dir, ".functions.js")) { // Now Try to load a Package, to test whether is is an assembly. try { ret.push({ content: (await import(resolve(fileName))).DESCRIPTION, path: fileName }); } catch (e) { getNopeLogger("helper-list-functions").error( "Failed Loading the functions in file: " + fileName ); getNopeLogger("helper-list-functions").error(e); } } return ret; } /** * Helper Function to write a default configuration. * * @export * @param {string} [dir='./modules'] * @param {string} [filename=join(resolve(process.cwd()), 'config', 'assembly.json')] */ export async function writeDefaultConfig( dir = "./modules", filename: string = join(resolve(process.cwd()), "config", "assembly.json") ) { // Determine all Packages const packages: IPackageConfig[] = (await listPackages(dir)).map((item) => { return { nameOfPackage: item.package.nameOfPackage, defaultInstances: item.package.defaultInstances, autostart: item.package.autostart, path: item.path }; }); const functions = (await listFunctions(dir)).map((item) => { return { path: item.path, functions: Object.getOwnPropertyNames(item.content || {}) }; }); await createFile( filename, JSON.stringify( { functions, packages }, undefined, 4 ) ); } /** * Function to load the Packages. * * @export * @param {INopePackageLoader} loader * @param {string} filename */ export async function loadPackages( loader: INopePackageLoader, filename: string = join(resolve(process.cwd()), "config", "assembly.json") ) { let data: IConfigFile = { functions: [], packages: [] }; try { /** Load the File and Parse it. */ data = JSON.parse(await readFile(filename, { encoding: "utf8" })); } catch (e) { // Generate the Default File await writeDefaultConfig(filename); // Show an Hint getNopeLogger("helper-load-packages").warn( "No configuration was present. Created a new config file in " + filename ); // Readin the newly created Data. data = JSON.parse( await readFile(filename, { encoding: "utf8" }) ); } // Define the Return Array. const packages = new Array>(); // Scan for the Package-Files // And iterate over them. for (const item of data.packages) { // Now Try to load a Package, to test whether is is an assembly. try { const loadedPackage = (await import(resolve(item.path))) .DESCRIPTION as IPackageDescription; loadedPackage.autostart = item.autostart; loadedPackage.defaultInstances = item.defaultInstances; packages.push(loadedPackage); } catch (e) { getNopeLogger("helper-load-packages").error( "Failed Loading the Package " + item.nameOfPackage ); getNopeLogger("helper-load-packages").error(e); } } await loader.dispatcher.ready.waitFor((value) => value === true); // Iterate over the Packages for (const thePackageToLoad of packages) { try { await loader.addPackage(thePackageToLoad); } catch (e) { getNopeLogger("helper-load-packages").error( "Failed Add the Package \"" + thePackageToLoad.nameOfPackage + "\" to the PackageLoader", e ); } } // Generate the instances. await loader.generateInstances(); } export async function loadFunctions( filename: string = join(resolve(process.cwd()), "config", "assembly.json") ) { let data: IConfigFile = { functions: [], packages: [] }; try { /** Load the File and Parse it. */ data = JSON.parse(await readFile(filename, { encoding: "utf8" })); } catch (e) { // Generate the Default File await writeDefaultConfig(filename); // Show an Hint getNopeLogger("helper-load-packages").warn( "No configuration was present. Created a new config file in " + filename ); // Readin the newly created Data. data = JSON.parse( await readFile(filename, { encoding: "utf8" }) ); } // Define the Return Array. const functionPackages = new Array(); // Scan for the Package-Files // And iterate over them. for (const item of data.functions) { // Now Try to load a Package, to test whether is is an assembly. try { const loadedFunction = (await import(resolve(item.path))) .DESCRIPTION as IPackageDescription; functionPackages.push(loadedFunction); } catch (e) { getNopeLogger("helper-load-packages").error( "Failed Loading function-file at " + item.path ); getNopeLogger("helper-load-packages").error(e); } } return functionPackages; }