const EngineScript = require("./enginescript.js");
const ExtensionScript = require("./extensionscript.js");
const path = require("path")
const fs = require("fs")
const manifest = {
name: "org.js.diddle.engine.extension",
version: "0.1"
}
function isClass(v) {
return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
}
/**
* @class
* @property {string} cwd The absolute directory where all of the custom Engine Extensions live.
* @extends {EngineScript}
*/
class EngineExtensionManager extends EngineScript {
/**
* @param {DiddleEngine} diddle
*/
constructor(diddle) {
super(diddle,manifest);
// Current Working Directory
this.cwd = '';
}
_ready() {
this._fetchExtensions();
}
_store = {
/*
<ScriptUID>: ExtensionScript
*/
}
/**
* @description Add Custom Engine Extension
* @param {ExtensionScript} extension
*/
append(extension) {
this._store[extension._ScriptUID] = extension;
}
/**
* @description Fetch Extension by its Unique Identifier
* @param {string} extension
* @returns {ExtensionScript}
*/
getByUID(ScriptUID) {
if (this._store[ScriptUID] == undefined) throw new Error(this.diddle.locale.get("ScriptExt.FetchFail.ExtensionNotFound"))
return this._store[ScriptUID];
}
/**
* @description Returns an Array of all Extensions that match the given name.
* @param {*} ScriptName
* @returns {ExtensionScript[]}
*/
getByName(ScriptName) {
return Object.entries(this._store).filter(script => script[1].manifest.name == ScriptName);
}
_fetchExtensions() {
var config = this.diddle.pacman.get("org.js.diddle.engine.config").get();
var timestamp_start = Date.now();
this.log.info(`fetching extensions...`);
this.cwd = path.resolve(config.extensions);
if (!fs.existsSync(this.cwd)) {
try {
fs.mkdirSync(this.cwd)
} catch(e) {
this.log.error(`cannot create extensions directory\n`,e);
process.exit(1);
}
this.log.info(`created extensions directory`);
}
// Get Script Files
var ext_filenames,ext_filtered = [];
try {
ext_filenames = fs.readdirSync(this.cwd).filter(f => f.endsWith(".js"));
} catch(e) {
this.log.error(`cannot fetch extensions directory\n`,e);
process.exit(1);
}
for (let i = 0; i < ext_filenames.length; i++) {
let current_filename = ext_filenames[i];
let current = require(path.join(this.cwd,current_filename));
if (isClass(current)) {
var ext = new current(this.diddle);
if (ext.manifest.name)
ext_filtered.push(ext);
this.log.debug(`loaded extension ${ext.manifest.name}@${ext.manifest.version} (${ext._ScriptUID})`)
} else {
this.log.error(`extension '${path.join(this.cwd,current_filename)}' cannot be constructed (isn't a class)`);
return;
}
}
this.extensions = ext_filtered;
this.log.info(`took ${Date.now() - timestamp_start}ms`);
}
}
module.exports = EngineExtensionManager;