0.0.1Updated a month ago
// deno-lint-ignore-file no-explicit-any

import { InstalledPlugin } from "../../classes/entities/installed_plugins.ts";
import { Core } from "../core.ts";
import type { Plugin } from "../plugin/plugin.ts";
import { PluginType } from "../plugin/plugin_type.ts";

export class PluginManager {
  private plugins: Plugin<any, any>[] = []
  private initialized = false

  constructor() {}

  get All() {
    return [...this.plugins];
  }

  Find(id: string) {
    return this.plugins.find(p => p.slug == id);
  }

  WithType(type: PluginType) {
    return this.plugins.filter(p => p.hasService(type));
  }

  Load(plugin: Plugin<any, any>) {
    plugin.services(PluginType.ComponentProvider)?.forEach(provider => {
      provider.components.map(component => {
        component.id = `${plugin.slug}::${component.id}`;
      })
    });

    this.plugins.push(plugin);

    (plugin as any).core = Core;

    if(this.initialized) plugin.init?.apply?.(plugin);

    console.log(`Plugin loaded [${plugin.name}] <${plugin.slug}@${plugin.version}>`);
  }

  async Init() {
    if(this.initialized) return false;
    
    const installed_plugins = await InstalledPlugin.find({});

    for(const installed_plugin of installed_plugins) {
      const import_data = await import(installed_plugin.url);
      if(!import_data.default) continue;

      const plugin = import_data.default as Plugin<any, any>;

      (plugin as any).config = installed_plugin.config;
      (plugin as any).reference_map = installed_plugin.reference_map;

      if(!('slug' in plugin && 'registerAs' in plugin)) continue;

      this.Load(plugin);
    }

    for(const plugin of this.plugins) {
      await plugin?.init?.apply(plugin);
    }

    return this.initialized = true;
  }
}