2021-05-02 17:42:04 -04:00
|
|
|
import Instance from './Instance.js';
|
|
|
|
|
import Serializable from './Serializable.js';
|
2021-05-06 09:33:28 -04:00
|
|
|
import _ from 'lodash';
|
2021-05-11 19:38:55 -04:00
|
|
|
import Module from './Module.js';
|
|
|
|
|
import debug from 'debug';
|
|
|
|
|
const log = debug('vogue:system')
|
2021-05-06 09:33:28 -04:00
|
|
|
|
|
|
|
|
const {get, set} = _;
|
2021-05-02 17:42:04 -04:00
|
|
|
|
|
|
|
|
export default class System extends Serializable {
|
|
|
|
|
instances = [];
|
|
|
|
|
modules = null;
|
2021-05-11 19:38:55 -04:00
|
|
|
namespace = null;
|
2021-05-12 00:15:53 -04:00
|
|
|
staticInstances = {};
|
2021-05-02 17:42:04 -04:00
|
|
|
|
2021-05-16 20:41:45 -04:00
|
|
|
constructor(modules, rootDir) {
|
2021-05-02 17:42:04 -04:00
|
|
|
super();
|
|
|
|
|
this.modules = modules;
|
2021-05-11 19:38:55 -04:00
|
|
|
this.createNamespace();
|
|
|
|
|
const bootModules = this.deriveBootModules();
|
2021-05-12 00:15:53 -04:00
|
|
|
this.createStaticInstances();
|
2021-05-16 20:41:45 -04:00
|
|
|
this.rootDir = rootDir;
|
2021-05-11 19:38:55 -04:00
|
|
|
|
2021-05-12 00:15:53 -04:00
|
|
|
log('instantiating boot modules...');
|
|
|
|
|
for(const name of bootModules) {
|
|
|
|
|
log(' ' + name);
|
2021-05-11 19:38:55 -04:00
|
|
|
this.newInstance(name);
|
2021-05-12 00:15:53 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createStaticInstances() {
|
|
|
|
|
log('deriving static modules...');
|
|
|
|
|
const staticModules = this.modules.filter((module) => {
|
|
|
|
|
return !!module.static;
|
|
|
|
|
}).map((module) => {
|
|
|
|
|
log(' ' + module.name.full);
|
|
|
|
|
return module;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
log('instantiating static modules...');
|
|
|
|
|
for(const module of staticModules) {
|
|
|
|
|
log(' ' + module.static + ': ' + module.name.full);
|
|
|
|
|
this.staticInstances[module.static] =
|
|
|
|
|
this.newInstance(module.name.full, {});
|
|
|
|
|
}
|
2021-05-11 19:38:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deriveBootModules() {
|
|
|
|
|
log('deriving boot modules...');
|
|
|
|
|
const bootModules = this.modules.filter((module) => {
|
|
|
|
|
return module.singleton;
|
|
|
|
|
}).map((module) => {
|
|
|
|
|
return module.name.full;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for(const name of bootModules)
|
|
|
|
|
log(' ' + name);
|
|
|
|
|
|
|
|
|
|
return bootModules;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createNamespace() {
|
|
|
|
|
log('creating namespace map...');
|
|
|
|
|
this.namespace = this.modules.reduce((acc, val) => {
|
|
|
|
|
if(get(acc, val.name.full) instanceof Module)
|
|
|
|
|
throw new Error('Duplicate module "' + val.name.full + '"');
|
|
|
|
|
set(acc, val.name.full, val);
|
|
|
|
|
log(' ' + val.name.full);
|
|
|
|
|
return acc;
|
|
|
|
|
}, {});
|
2021-05-06 09:33:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getModule(name) {
|
2021-05-11 19:38:55 -04:00
|
|
|
return get(this.namespace, name);
|
2021-05-02 17:42:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createInstance(name, args = {}) {
|
2021-05-06 09:33:28 -04:00
|
|
|
return new Instance(this.getModule(name), null, args, this);
|
2021-05-02 17:42:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newInstance(name, args = {}) {
|
|
|
|
|
const instance = this.createInstance(name, args);
|
2021-05-06 23:05:36 -04:00
|
|
|
const link = instance.link;
|
2021-05-12 00:15:53 -04:00
|
|
|
if(instance.hasPublicFunction('restore'))
|
|
|
|
|
instance.invokeInternal('restore');
|
2021-05-02 17:42:04 -04:00
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|