import isPlainObject from 'lodash/isPlainObject';
import mergeWith from 'lodash/mergeWith';
import pick from 'lodash/pick';
import { log } from '@ae.sdp.nd/utils/src/debug';
import Core from './Core';
import Plugin from './Plugin';
interface Options {
[key: string]: any;
}
export default abstract class Framework {
public static Plugins: typeof Plugin[] = [];
public static options: Object = {
plugins: {},
};
private core: Core;
private options?: Options;
constructor(options: Options = {}) {
// 递归合并
this.options = this.getOptions(options);
if (process.env.NODE_ENV !== 'production') log('所有配置项 %O', this.options);
// 仅取所需
this.core = new Core(pick(this.options, [
'modules',
'container',
]));
}
public mount() {
// TODO Plugins 与 options 放到同一个方法类去处理,看上去更清晰?
const Plugins = this.getPlugins();
if (process.env.NODE_ENV !== 'production') log('启用的插件 %O', Plugins);
// 从插件取 core 需要的配置项
const propsForCore = merge(...Plugins.map((_Plugin: any) => {
// 取插件的 configs
const pluginConfig = this.options.plugins[_Plugin.Name.toLowerCase()] || {};
return new _Plugin(pluginConfig, this.core).apply();
}));
if (process.env.NODE_ENV !== 'production') log('为 Core 生成配置项 %O', propsForCore);
// 合入到 core
this.core.setProps(propsForCore);
// 挂载!
return this.core.mount();
}
private getPlugins() {
let ctr: any = this.constructor;
const Plugins = [...ctr.Plugins];
// 自动继承父类的 静态属性 Plugins
// tslint:disable-next-line
while (ctr && (ctr = Object.getPrototypeOf(ctr))) {
if (ctr.Plugins) {
Plugins.unshift(...ctr.Plugins);
}
}
// 检查插件依赖
if (process.env.NODE_ENV !== 'production') {
require('@ae.sdp.nd/utils/src/check-plugins-deps').default(Plugins);
}
return Plugins;
}
private getOptions(options: Options) {
let ctr: any = this.constructor;
const optionsList = [ctr.options];
// 自动继承父类的 静态属性 options
// tslint:disable-next-line
while (ctr && (ctr = Object.getPrototypeOf(ctr))) {
if (ctr.options) {
optionsList.unshift(ctr.options);
}
}
return merge(...optionsList, options);
}
}
function merge(...args) {
return mergeWith({}, ...args, (object: any, source: any) => {
// 合并数组
if (Array.isArray(source)) {
if (Array.isArray(object)) {
return object.concat(source);
}
}
// 合并对象
if (isPlainObject(source)) {
if (isPlainObject(object)) {
return merge(object, source);
}
}
// 其它,直接覆盖
return object;
});
}
|