import fs from "fs";
import path from "path";
import vm from "vm";

export class LoadComponent {
  componentsPath: string = path.resolve("../first/components/");
  componentName: string = "";
  componentIndex: string = "";

  loadCodeFile() {
    this.componentIndex = path.join(
      this.componentsPath,
      this.componentName,
      "res/js/index.js"
    );

    const file = fs.readFileSync(this.componentIndex).toString();

    return file;
  }

  loadComponent(componentName: string) {
    this.componentName = componentName;

    const componentFolder = fs
      .readdirSync(this.componentsPath)
      .find((val) => val === componentName);

    if (componentFolder === undefined) throw Error("component does not exist!");

    interface sample {
      name: string;
      params: string[];
      entity: (...args: any) => any;
    }
    // mock require
    const repository: sample[] = [];

    const collectParams = (arr: string[], exports: object) => {
      return arr.map((val) => {
        if (val === "exports") return exports;
        val = path.join(this.componentsPath, val);
        if (cache[val]) return cache[val];
        let rep = repository.find((rep) => rep.name === val);
        if (rep === undefined) {
          if (!fs.existsSync(val)) return undefined;
          aux.window.modulePath = val;
          const defineModule = fs.readFileSync(val).toString();
          const script = new vm.Script(defineModule);
          vm.createContext(aux);
          script.runInContext(aux);

          rep = repository.find((rep) => rep.name === val) as sample;
        }

        let exportsObj: any = {};
        const ret = rep.entity(...collectParams(rep.params, exportsObj));
        cache[val] = ret ? ret : exportsObj;

        return cache[val];
      });
    };

    const moduleRequire = (...args: any) => {
      let prep: any[] = [];
      if (Object.prototype.toString.call(args[0]) === "[object Array]") {
        const first = args[0] as string[];
        const exportObj = {};
        prep = collectParams(first, exportObj);
      }

      if (Object.prototype.toString.call(args[1]) === "[object Function]") {
        args[1](...prep);
      }
    };

    const cache: { [moduleName: string]: any } = {
      require: moduleRequire,
    };

    // mock require end
    const script = new vm.Script(
      this.loadCodeFile() +
        `\n require(['/${this.componentName}/res/js/index.js'], (module)=>{ window.auxClass = Object.values(module)[0] })`
    );

    const aux = {
      window: {
        auxClass: null,
        modulePath: this.componentIndex,
      },
      require: moduleRequire,
      define: (params: string[], fun: (...args: any) => undefined | object) => {
        repository.push({
          name: aux.window.modulePath,
          params,
          entity: fun,
        });
      },
      // console,
    };

    vm.createContext(aux);

    script.runInContext(aux);

    return aux.window.auxClass;
  }
}
  loadTest() {
    const load = new LoadComponent();
    const com = load.loadComponent("head");
    console.log(com);
  }

 

 posted on 2024-03-21 16:27  laremehpe  阅读(5)  评论(0编辑  收藏  举报