All files Framework.ts

23.08% Statements 12/52
0% Branches 0/28
12.5% Functions 1/8
25.53% Lines 12/47
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 982x 2x 2x 2x 2x             2x 2x 2x                                   2x                                 2x                                 2x                       2x                                        
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;
  });
}