"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _fs=_interopRequireDefault(require("fs"));
var _path=_interopRequireDefault(require("path"));

var _helpers=require("../helpers");function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);if(enumerableOnly)symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable});keys.push.apply(keys,symbols)}return keys}function _objectSpread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};if(i%2){ownKeys(Object(source),true).forEach(function(key){(0,_defineProperty2.default)(target,key,source[key])})}else if(Object.getOwnPropertyDescriptors){Object.defineProperties(target,Object.getOwnPropertyDescriptors(source))}else{ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}}return target}let _require=

require("@corenode/utils"),verbosity=_require.verbosity,objectToArrayMap=_require.objectToArrayMap;
verbosity=verbosity.options({method:`[MODULES]`,time:false});const _require2=

require("../vm"),EvalMachine=_require2.EvalMachine;

const defaults={
loader:`load.module.js`,
registryObjectName:`modules`,
localModulesPathname:`modules`};


class ModuleController{
constructor(){(0,_defineProperty2.default)(this,"fetchInternals",



























































()=>this.fetch(this.internalModulesPath));(0,_defineProperty2.default)(this,"fetchExternals",

()=>this.fetch(this.externalModulesPath));(0,_defineProperty2.default)(this,"registryKey",



































































































































{
add:(key,value)=>{
let registry=this.getRegistry();
registry[key]=value!==null&&value!==void 0?value:"0.0.0";

this.writeRegistry(registry);
},
remove:key=>{
let registry=this.getRegistry();
registry=delete registry[key];

this.writeRegistry(registry);
}});if(typeof global.corenode==="undefined"){throw new Error(`corenode runtime has not been initialized`)}this.defaultLoader=defaults.loader;this.registryObjectName=defaults.registryObjectName;this.localModulesPathname=defaults.localModulesPathname;this.externalModulesPath=_path.default.resolve(process.cwd(),defaults.localModulesPathname);this.internalModulesPath=_path.default.resolve(global._runtimeRoot,"packages");this._modules={};this._libraries={};this.init()}isOnRegistry(key){return this.getRegistry(key)?true:false}readLoader(loader){return require(loader)}resolveLoader(origin){let loaders=[];let dirs=[];if(typeof origin==="string"){dirs.push(origin)}if(Array.isArray(origin)){dirs=origin}dirs.forEach(dir=>{const loader=`${dir}/${this.defaultLoader}`;if(_fs.default.existsSync(loader)){loaders.push(loader)}});return loaders}fetch(origin){const modules=[];if(_fs.default.existsSync(origin)){_fs.default.readdirSync(origin).forEach(dir=>{const modulesPath=_path.default.resolve(origin,dir);if(_fs.default.existsSync(modulesPath)){modules.push(modulesPath)}})}return this.resolveLoader(modules)}fetchModules(){const modules={};const allModules=[];const internals=this.fetchInternals();const externals=this.fetchExternals();if(internals.length>0)allModules.push(...internals);if(externals.length>0)allModules.push(...externals);allModules.forEach(loader=>{const _module=this.readLoader(loader);const pkg=_module.pkg;modules[pkg]={internal:internals.includes(loader),loader}});return modules}getRegistry(key){var _packageJSON$defaults;const packageJSON=(0,_helpers.getRootPackage)();const registry=(_packageJSON$defaults=packageJSON[defaults.registryObjectName])!==null&&_packageJSON$defaults!==void 0?_packageJSON$defaults:{};if(key){return registry[key]}return registry}getLoadedModules(){return this._modules}getLoadedLibraries(){return this._libraries}getExternalModulesPath(){return this.externalModulesPath}loadModule(loader){var _loader$internal;let context={};try{if(typeof loader==="string"){if(_fs.default.existsSync(loader)){if(!loader.includes(`load.module.js`)){loader=_path.default.resolve(loader,`load.module.js`)}const loaderFile=loader;loader=this.readLoader(loader);loader.file=loaderFile}}}catch(error){verbosity.dump(error);verbosity.error(`Failed to load external module > [${loader}] >`,error.message);return false}loader.meta={version:loader.version};loader.dirname=_path.default.dirname(loader.file);if(typeof loader.pkg==="undefined"){throw new Error(`Invalid module, missing [pkg]`)}if(typeof loader.script!=="undefined"){try{const loaderScriptPath=_path.default.resolve(loader.dirname,loader.script);if(!_fs.default.existsSync(loaderScriptPath)){return verbosity.error(`[${loader.pkg}] Script file not exists: `+loaderScriptPath)}const machine=new EvalMachine({eval:loaderScriptPath,cwd:loader.dirname});context["script"]=machine;process.runtime.appendToController(`${loader.pkg}`,(...context)=>machine.run(...context))}catch(error){verbosity.dump(error);verbosity.options({method:`[VM]`}).error(`[${loader.pkg}] Failed at vm initalization >`,error)}}if(typeof loader.appendCli!=="undefined"){if(Array.isArray(loader.appendCli)){loader.appendCli.forEach(entry=>{if(typeof global.corenode_cli.custom=="undefined"){global.corenode_cli.custom=[]}global.corenode_cli.custom.push(_objectSpread(_objectSpread({},entry),{},{exec:(...args)=>entry.exec(context,...args)}))})}}if(typeof loader.init==="function"){try{loader.init({})}catch(error){verbosity.dump(error);verbosity.error(`Failed at module initialization > [${loader.pkg}] >`,error.message)}}const manifest={loader:loader.file,meta:loader.meta,internal:(_loader$internal=loader.internal)!==null&&_loader$internal!==void 0?_loader$internal:false};this._modules[loader.pkg]=manifest;return manifest}unloadModule(key){delete this.pool[key];delete this._modules[key]}


writeRegistry(registry){
if(!registry)return false;
const packageJSONPath=_path.default.resolve(process.cwd(),"package.json");
let packageJSON=(0,_helpers.getRootPackage)();

if(typeof packageJSON!=="object"){
throw new Error(`Invalid typeof >> package.json is not an object`);
}

packageJSON[this.registryObjectName]=registry;
_fs.default.writeFileSync(packageJSONPath,JSON.stringify(packageJSON,null,2),{encoding:"utf8"});
}

init(){
const allModules=this.fetchModules();
const registry=this.getRegistry();

objectToArrayMap(allModules).forEach(manifest=>{
if(typeof this._modules[manifest.key]==="undefined"){const
internal=manifest.value.internal;

if(internal||this.isOnRegistry(manifest.key)){
const loader=this.readLoader(manifest.value.loader);
const _module=this.loadModule(_objectSpread(_objectSpread({},loader),{},{internal:internal,file:manifest.value.loader}));

if(!_module){
return false;
}const

meta=_module.meta;

if(!internal){
const fromReg=this.getRegistry(manifest.key);
if(typeof fromReg!=="undefined"&&typeof meta.version!=="undefined"){
if(meta.version!==fromReg){
verbosity.
options({dumpFile:true}).
warn(`Module version conflict (${manifest.key}@${fromReg}) > Loaded (${manifest.key}@${meta.version})`);
}
}else{
verbosity.options({dumpFile:"only"}).warn(`Version control is not available for module (${manifest.key})`);
}
}
}
}
});


objectToArrayMap(registry).forEach(entry=>{
let loader=null;

const asPath=_path.default.resolve(entry.value);
if(_fs.default.existsSync(asPath)){
loader=asPath;
}else{

}


this.loadModule(loader);
});
}}exports.default=ModuleController;