2020-11-11 16:08:11 +00:00
|
|
|
/**
|
|
|
|
* @author Martin Karkowski
|
|
|
|
* @email m.karkowski@zema.de
|
|
|
|
* @desc [description]
|
|
|
|
*/
|
|
|
|
|
|
|
|
import { readFile } from "fs/promises";
|
|
|
|
import { join, resolve } from "path";
|
|
|
|
import "reflect-metadata";
|
2021-10-18 18:46:06 +00:00
|
|
|
import { sleep } from "../helpers/async";
|
2020-12-04 18:10:33 +00:00
|
|
|
import { createFile, listFiles } from "../helpers/fileMethods";
|
2022-03-19 06:39:12 +00:00
|
|
|
import { parseWithFunctions, stringifyWithFunctions } from "../index.browser";
|
2020-11-11 16:08:11 +00:00
|
|
|
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";
|
|
|
|
|
2020-11-12 16:07:05 +00:00
|
|
|
export interface IPackageConfig {
|
2020-12-04 18:10:33 +00:00
|
|
|
nameOfPackage: string;
|
|
|
|
defaultInstances: {
|
|
|
|
options: Partial<IInstanceCreationMsg>;
|
|
|
|
selector: string | symbol;
|
|
|
|
}[];
|
|
|
|
autostart: {
|
|
|
|
[index: string]: {
|
2020-12-30 18:55:32 +00:00
|
|
|
service: string;
|
2020-12-04 18:10:33 +00:00
|
|
|
delay?: number;
|
|
|
|
params: any[];
|
2020-11-11 16:08:11 +00:00
|
|
|
}[];
|
2020-12-04 18:10:33 +00:00
|
|
|
};
|
|
|
|
// File Path of the element.
|
|
|
|
path: string;
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
|
|
|
|
2020-11-12 16:07:05 +00:00
|
|
|
export interface IConfigFile {
|
2020-12-04 18:10:33 +00:00
|
|
|
functions: {
|
|
|
|
path: string;
|
|
|
|
functions: [];
|
|
|
|
}[];
|
|
|
|
packages: IPackageConfig[];
|
2020-11-12 16:07:05 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 16:08:11 +00:00
|
|
|
/**
|
|
|
|
* List the available Packages
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {string} [dir='./modules']
|
2020-12-04 18:10:33 +00:00
|
|
|
* @return {*}
|
2020-11-11 16:08:11 +00:00
|
|
|
*/
|
2020-12-04 18:10:33 +00:00
|
|
|
export async function listPackages(dir = "./modules") {
|
|
|
|
// Define the Return Array.
|
|
|
|
const ret = new Array<{
|
|
|
|
package: IPackageDescription<any>;
|
|
|
|
path: string;
|
|
|
|
}>();
|
2020-11-11 16:08:11 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
// 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<any>,
|
2021-12-04 07:25:26 +00:00
|
|
|
path: fileName,
|
2020-12-04 18:10:33 +00:00
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
getNopeLogger("helper-list-packages").error(
|
|
|
|
"Failed Loading the Package " + fileName
|
|
|
|
);
|
|
|
|
getNopeLogger("helper-list-packages").error(e);
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-11 16:08:11 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
return ret;
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
export async function listFunctions(dir = "./modules") {
|
|
|
|
// Define the Return Array.
|
|
|
|
const ret = new Array<{
|
|
|
|
content: any;
|
|
|
|
path: string;
|
|
|
|
}>();
|
2020-11-12 16:07:05 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
// 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,
|
2021-12-04 07:25:26 +00:00
|
|
|
path: fileName,
|
2020-12-04 18:10:33 +00:00
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
getNopeLogger("helper-list-functions").error(
|
|
|
|
"Failed Loading the functions in file: " + fileName
|
|
|
|
);
|
|
|
|
getNopeLogger("helper-list-functions").error(e);
|
2020-11-12 16:07:05 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-12 16:07:05 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
return ret;
|
2020-11-12 16:07:05 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 16:08:11 +00:00
|
|
|
/**
|
|
|
|
* 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(
|
2020-12-04 18:10:33 +00:00
|
|
|
dir = "./modules",
|
|
|
|
filename: string = join(resolve(process.cwd()), "config", "assembly.json")
|
2020-11-11 16:08:11 +00:00
|
|
|
) {
|
2020-12-04 18:10:33 +00:00
|
|
|
// Determine all Packages
|
|
|
|
const packages: IPackageConfig[] = (await listPackages(dir)).map((item) => {
|
|
|
|
return {
|
|
|
|
nameOfPackage: item.package.nameOfPackage,
|
|
|
|
defaultInstances: item.package.defaultInstances,
|
|
|
|
autostart: item.package.autostart,
|
2021-12-04 07:25:26 +00:00
|
|
|
path: item.path,
|
2020-12-04 18:10:33 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
const functions = (await listFunctions(dir)).map((item) => {
|
|
|
|
return {
|
|
|
|
path: item.path,
|
2021-12-04 07:25:26 +00:00
|
|
|
functions: Object.getOwnPropertyNames(item.content || {}),
|
2020-12-04 18:10:33 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
await createFile(
|
|
|
|
filename,
|
2022-03-19 06:39:12 +00:00
|
|
|
stringifyWithFunctions(
|
2020-12-04 18:10:33 +00:00
|
|
|
{
|
2020-11-12 16:07:05 +00:00
|
|
|
functions,
|
2021-12-04 07:25:26 +00:00
|
|
|
packages,
|
2020-12-04 18:10:33 +00:00
|
|
|
},
|
|
|
|
4
|
|
|
|
)
|
|
|
|
);
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to load the Packages.
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {INopePackageLoader} loader
|
|
|
|
* @param {string} filename
|
|
|
|
*/
|
2020-12-04 18:10:33 +00:00
|
|
|
export async function loadPackages(
|
|
|
|
loader: INopePackageLoader,
|
2021-10-18 18:46:06 +00:00
|
|
|
filename: string = join(resolve(process.cwd()), "config", "settings.json"),
|
|
|
|
delay = 2
|
2020-12-04 18:10:33 +00:00
|
|
|
) {
|
|
|
|
let data: IConfigFile = {
|
|
|
|
functions: [],
|
2021-12-04 07:25:26 +00:00
|
|
|
packages: [],
|
2020-12-04 18:10:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
/** Load the File and Parse it. */
|
2022-03-19 06:39:12 +00:00
|
|
|
data = parseWithFunctions(await readFile(filename, { encoding: "utf8" }));
|
2020-12-04 18:10:33 +00:00
|
|
|
} 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, {
|
2021-12-04 07:25:26 +00:00
|
|
|
encoding: "utf8",
|
2020-12-04 18:10:33 +00:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Define the Return Array.
|
|
|
|
const packages = new Array<IPackageDescription<any>>();
|
|
|
|
|
|
|
|
// 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.
|
2020-11-11 16:08:11 +00:00
|
|
|
try {
|
2020-12-04 18:10:33 +00:00
|
|
|
const loadedPackage = (await import(resolve(item.path)))
|
|
|
|
.DESCRIPTION as IPackageDescription<any>;
|
|
|
|
loadedPackage.autostart = item.autostart;
|
|
|
|
loadedPackage.defaultInstances = item.defaultInstances;
|
|
|
|
packages.push(loadedPackage);
|
2020-11-11 16:08:11 +00:00
|
|
|
} catch (e) {
|
2020-12-04 18:10:33 +00:00
|
|
|
getNopeLogger("helper-load-packages").error(
|
|
|
|
"Failed Loading the Package " + item.nameOfPackage
|
|
|
|
);
|
|
|
|
getNopeLogger("helper-load-packages").error(e);
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-11 16:08:11 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
await loader.dispatcher.ready.waitFor((value) => value === true);
|
2020-11-15 19:11:25 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
// Iterate over the Packages
|
|
|
|
for (const thePackageToLoad of packages) {
|
|
|
|
try {
|
|
|
|
await loader.addPackage(thePackageToLoad);
|
|
|
|
} catch (e) {
|
|
|
|
getNopeLogger("helper-load-packages").error(
|
2021-12-04 07:25:26 +00:00
|
|
|
'Failed Add the Package "' +
|
|
|
|
thePackageToLoad.nameOfPackage +
|
|
|
|
'" to the PackageLoader',
|
2020-12-04 18:10:33 +00:00
|
|
|
e
|
|
|
|
);
|
2020-11-11 16:08:11 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-11 16:08:11 +00:00
|
|
|
|
2021-10-18 18:46:06 +00:00
|
|
|
if (delay > 0) {
|
2021-12-04 07:25:26 +00:00
|
|
|
getNopeLogger("helper-load-packages").info(
|
|
|
|
`Waiting ${delay} [s] before creating instances.`
|
|
|
|
);
|
2021-10-18 18:46:06 +00:00
|
|
|
await sleep(delay * 1000);
|
|
|
|
}
|
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
// Generate the instances.
|
|
|
|
await loader.generateInstances();
|
2020-11-12 16:07:05 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
export async function loadFunctions(
|
|
|
|
filename: string = join(resolve(process.cwd()), "config", "assembly.json")
|
|
|
|
) {
|
|
|
|
let data: IConfigFile = {
|
|
|
|
functions: [],
|
2021-12-04 07:25:26 +00:00
|
|
|
packages: [],
|
2020-12-04 18:10:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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, {
|
2021-12-04 07:25:26 +00:00
|
|
|
encoding: "utf8",
|
2020-12-04 18:10:33 +00:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Define the Return Array.
|
|
|
|
const functionPackages = new Array<any>();
|
|
|
|
|
|
|
|
// 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.
|
2020-11-12 16:07:05 +00:00
|
|
|
try {
|
2020-12-04 18:10:33 +00:00
|
|
|
const loadedFunction = (await import(resolve(item.path)))
|
|
|
|
.DESCRIPTION as IPackageDescription<any>;
|
|
|
|
functionPackages.push(loadedFunction);
|
2020-11-12 16:07:05 +00:00
|
|
|
} catch (e) {
|
2020-12-04 18:10:33 +00:00
|
|
|
getNopeLogger("helper-load-packages").error(
|
|
|
|
"Failed Loading function-file at " + item.path
|
|
|
|
);
|
|
|
|
getNopeLogger("helper-load-packages").error(e);
|
2020-11-12 16:07:05 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-12 16:07:05 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
return functionPackages;
|
|
|
|
}
|