@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import { plugin as pluginApi } from "@ccms/api"
 | 
				
			||||||
import { injectable, decorate } from "@ccms/container"
 | 
					import { injectable, decorate } from "@ccms/container"
 | 
				
			||||||
import { interfaces } from './interfaces'
 | 
					import { interfaces } from './interfaces'
 | 
				
			||||||
import { METADATA_KEY } from './constants'
 | 
					import { METADATA_KEY } from './constants'
 | 
				
			||||||
@@ -7,16 +8,16 @@ import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata
 | 
				
			|||||||
 * MiaoScript plugin
 | 
					 * MiaoScript plugin
 | 
				
			||||||
 * @param metadata PluginMetadata
 | 
					 * @param metadata PluginMetadata
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function plugin(metadata: interfaces.PluginMetadata) {
 | 
					export function plugin(metadata: pluginApi.PluginMetadata) {
 | 
				
			||||||
    return function (target: any) {
 | 
					    return function (target: any) {
 | 
				
			||||||
        metadata.target = target
 | 
					        metadata.target = target
 | 
				
			||||||
        metadata.type = "ioc"
 | 
					        metadata.type = "ioc"
 | 
				
			||||||
        decorate(injectable(), target)
 | 
					        decorate(injectable(), target)
 | 
				
			||||||
        Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target)
 | 
					        Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target)
 | 
				
			||||||
        const previousMetadata: Map<string, interfaces.PluginMetadata> = getPluginMetadatas()
 | 
					        const previousMetadata: Map<string, pluginApi.PluginMetadata> = getPluginMetadatas()
 | 
				
			||||||
        previousMetadata.set(metadata.name, metadata)
 | 
					        previousMetadata.set(metadata.name, metadata)
 | 
				
			||||||
        Reflect.defineMetadata(METADATA_KEY.plugin, previousMetadata, Reflect)
 | 
					        Reflect.defineMetadata(METADATA_KEY.plugin, previousMetadata, Reflect)
 | 
				
			||||||
        const previousSources: Map<string, interfaces.PluginMetadata> = getPluginSources()
 | 
					        const previousSources: Map<string, pluginApi.PluginMetadata> = getPluginSources()
 | 
				
			||||||
        previousSources.set(metadata.source.toString(), metadata)
 | 
					        previousSources.set(metadata.source.toString(), metadata)
 | 
				
			||||||
        Reflect.defineMetadata(METADATA_KEY.souece, previousSources, Reflect)
 | 
					        Reflect.defineMetadata(METADATA_KEY.souece, previousSources, Reflect)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,15 @@
 | 
				
			|||||||
 | 
					import './scanner/file-scanner'
 | 
				
			||||||
 | 
					import './loader/ioc-loader'
 | 
				
			||||||
 | 
					import './loader/basic-loader'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export * from './manager'
 | 
					export * from './manager'
 | 
				
			||||||
export * from './decorators'
 | 
					export * from './decorators'
 | 
				
			||||||
export * from './interfaces'
 | 
					export * from './interfaces'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export {
 | 
				
			||||||
 | 
					    plugin as JSPlugin,
 | 
				
			||||||
 | 
					    cmd as Cmd,
 | 
				
			||||||
 | 
					    tab as Tab,
 | 
				
			||||||
 | 
					    listener as Listener,
 | 
				
			||||||
 | 
					    config as Config
 | 
				
			||||||
 | 
					} from './decorators'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,14 @@
 | 
				
			|||||||
import { server, MiaoScriptConsole, event, plugin } from "@ccms/api";
 | 
					import { server, MiaoScriptConsole, event, plugin } from "@ccms/api"
 | 
				
			||||||
import { injectable, inject, postConstruct } from "@ccms/container";
 | 
					import { injectable, inject, postConstruct } from "@ccms/container"
 | 
				
			||||||
import { getPluginMetadata } from "./utils";
 | 
					import { getPluginMetadata } from "./utils"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export namespace interfaces {
 | 
					export namespace interfaces {
 | 
				
			||||||
    @injectable()
 | 
					    @injectable()
 | 
				
			||||||
    export abstract class Plugin implements plugin.Plugin {
 | 
					    export abstract class Plugin implements plugin.Plugin {
 | 
				
			||||||
        public description: PluginMetadata;
 | 
					        public description: plugin.PluginMetadata
 | 
				
			||||||
        public logger: Console;
 | 
					        public logger: Console
 | 
				
			||||||
        @inject(server.Console)
 | 
					        @inject(server.Console)
 | 
				
			||||||
        private Console: MiaoScriptConsole;
 | 
					        private Console: MiaoScriptConsole
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        constructor() {
 | 
					        constructor() {
 | 
				
			||||||
            this.description = getPluginMetadata(this)
 | 
					            this.description = getPluginMetadata(this)
 | 
				
			||||||
@@ -24,86 +24,45 @@ export namespace interfaces {
 | 
				
			|||||||
        public enable() { }
 | 
					        public enable() { }
 | 
				
			||||||
        public disable() { }
 | 
					        public disable() { }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    interface BaseMetadata {
 | 
					    export interface ExecMetadata extends plugin.BaseMetadata {
 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 名称 为空则为对象名称
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        name?: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 支持的服务器列表 为空则代表所有
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        servers?: string[];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    export interface PluginMetadata extends BaseMetadata {
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件名称
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        name: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 前缀
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        prefix?: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件版本
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        version: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件版本
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        author: string | string[];
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件源文件 必须指定为 __filename
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        source: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件类型 默认为 ioc 执行 MiaoScript 加载逻辑
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        type?: string;
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 插件本体
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        target?: any;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    export interface ExecMetadata extends BaseMetadata {
 | 
					 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 执行器
 | 
					         * 执行器
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        executor?: string;
 | 
					        executor?: string
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    export interface CommandMetadata extends ExecMetadata {
 | 
					    export interface CommandMetadata extends ExecMetadata {
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 参数列表
 | 
					         * 参数列表
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        paramtypes?: string[];
 | 
					        paramtypes?: string[]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    export interface ListenerMetadata extends ExecMetadata {
 | 
					    export interface ListenerMetadata extends ExecMetadata {
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 监听优先级
 | 
					         * 监听优先级
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        priority?: event.EventPriority;
 | 
					        priority?: event.EventPriority
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 是否忽略已取消的事件
 | 
					         * 是否忽略已取消的事件
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        ignoreCancel?: boolean;
 | 
					        ignoreCancel?: boolean
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    export interface ConfigMetadata extends BaseMetadata {
 | 
					    export interface ConfigMetadata extends plugin.BaseMetadata {
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 配置文件版本号
 | 
					         * 配置文件版本号
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        version?: number;
 | 
					        version?: number
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 实体变量名称
 | 
					         * 实体变量名称
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        variable?: string;
 | 
					        variable?: string
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 配置文件格式 默认 yml
 | 
					         * 配置文件格式 默认 yml
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        format?: string;
 | 
					        format?: string
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 是否为只读(关闭时将不会自动保存)
 | 
					         * 是否为只读(关闭时将不会自动保存)
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        readonly?: boolean;
 | 
					        readonly?: boolean
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    export type PluginLike = Plugin | string;
 | 
					    export type PluginLike = Plugin | string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								packages/plugin/src/loader/basic-loader.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								packages/plugin/src/loader/basic-loader.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import { plugin } from "@ccms/api"
 | 
				
			||||||
 | 
					import { provideSingleton } from "@ccms/container"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@provideSingleton(plugin.PluginLoader)
 | 
				
			||||||
 | 
					export class BasicLoader implements plugin.PluginLoader {
 | 
				
			||||||
 | 
					    type: string = 'basic'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private pluginRequireMap: Map<string, any>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.pluginRequireMap = new Map()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    require(target: any, result: any) {
 | 
				
			||||||
 | 
					        this.pluginRequireMap.set(target.toString(), result)
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    build(metadata: plugin.PluginMetadata) {
 | 
				
			||||||
 | 
					        return this.pluginRequireMap.get(metadata.source.toString())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    load(plugin: plugin.Plugin): void { }
 | 
				
			||||||
 | 
					    enable(plugin: plugin.Plugin): void { }
 | 
				
			||||||
 | 
					    disable(plugin: plugin.Plugin): void { }
 | 
				
			||||||
 | 
					    reload(plugin: plugin.Plugin): void { }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										97
									
								
								packages/plugin/src/loader/ioc-loader.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								packages/plugin/src/loader/ioc-loader.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					import { plugin, server } from "@ccms/api"
 | 
				
			||||||
 | 
					import { inject, ContainerInstance, Container, provideSingleton } from "@ccms/container"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { interfaces } from "../interfaces"
 | 
				
			||||||
 | 
					import { getPluginStageMetadata, getPluginSources } from "../utils"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@provideSingleton(plugin.PluginLoader)
 | 
				
			||||||
 | 
					export class IocLoader implements plugin.PluginLoader {
 | 
				
			||||||
 | 
					    type: string = 'ioc'
 | 
				
			||||||
 | 
					    @inject(ContainerInstance)
 | 
				
			||||||
 | 
					    private container: Container
 | 
				
			||||||
 | 
					    @inject(server.ServerType)
 | 
				
			||||||
 | 
					    private serverType: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private pluginMetadataMap: Map<string, plugin.PluginMetadata>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.pluginMetadataMap = getPluginSources()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    require(target: any, result: any) {
 | 
				
			||||||
 | 
					        return this.pluginMetadataMap.get(target.toString())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build(metadata: plugin.PluginMetadata) {
 | 
				
			||||||
 | 
					        if (!this.allowProcess(metadata.servers)) { return }
 | 
				
			||||||
 | 
					        let pluginInstance: plugin.Plugin
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            this.bindPlugin(metadata)
 | 
				
			||||||
 | 
					            pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
				
			||||||
 | 
					            if (!(pluginInstance instanceof interfaces.Plugin)) {
 | 
				
			||||||
 | 
					                console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (ex) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.initialize.error", { name: metadata.name, ex })
 | 
				
			||||||
 | 
					            console.ex(ex)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return pluginInstance
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    load(plugin: plugin.Plugin): void {
 | 
				
			||||||
 | 
					        this.stage(plugin, 'load')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    enable(plugin: plugin.Plugin): void {
 | 
				
			||||||
 | 
					        this.stage(plugin, 'enable')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    disable(plugin: plugin.Plugin): void {
 | 
				
			||||||
 | 
					        this.stage(plugin, 'disable')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    reload(plugin: plugin.Plugin): void {
 | 
				
			||||||
 | 
					        this.disable(plugin)
 | 
				
			||||||
 | 
					        //@ts-ignore
 | 
				
			||||||
 | 
					        require(plugin.description.source, { cache: false })
 | 
				
			||||||
 | 
					        this.load(plugin)
 | 
				
			||||||
 | 
					        this.enable(plugin)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private bindPlugin(metadata: plugin.PluginMetadata) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
				
			||||||
 | 
					            if (pluginInstance.description.source + '' !== metadata.source + '') {
 | 
				
			||||||
 | 
					                console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
 | 
				
			||||||
 | 
					        } catch{
 | 
				
			||||||
 | 
					            this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private allowProcess(servers: string[]) {
 | 
				
			||||||
 | 
					        // Not set servers -> allow
 | 
				
			||||||
 | 
					        if (!servers || !servers.length) return true
 | 
				
			||||||
 | 
					        // include !type -> deny
 | 
				
			||||||
 | 
					        let denyServers = servers.filter(svr => svr.startsWith("!"))
 | 
				
			||||||
 | 
					        if (denyServers.length !== 0) {
 | 
				
			||||||
 | 
					            return !denyServers.includes(`!${this.serverType}`)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // only include -> allow
 | 
				
			||||||
 | 
					            return servers.includes(this.serverType)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private stage(pluginInstance: plugin.Plugin, stageName: string) {
 | 
				
			||||||
 | 
					        let stages = getPluginStageMetadata(pluginInstance, stageName)
 | 
				
			||||||
 | 
					        for (const stage of stages) {
 | 
				
			||||||
 | 
					            if (!this.allowProcess(stage.servers)) { continue }
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.stage.exec", { plugin: pluginInstance.description.name, name: stage.executor, stage: stageName, servers: stage.servers })
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                pluginInstance[stage.executor].apply(pluginInstance)
 | 
				
			||||||
 | 
					            } catch (error) {
 | 
				
			||||||
 | 
					                console.i18n("ms.plugin.manager.stage.exec.error", { plugin: pluginInstance.description.name, executor: stage.executor, error })
 | 
				
			||||||
 | 
					                console.ex(error)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,9 +3,9 @@ import { plugin, server, command, event } from '@ccms/api'
 | 
				
			|||||||
import { inject, provideSingleton, Container, ContainerInstance } from '@ccms/container'
 | 
					import { inject, provideSingleton, Container, ContainerInstance } from '@ccms/container'
 | 
				
			||||||
import * as fs from '@ccms/common/dist/fs'
 | 
					import * as fs from '@ccms/common/dist/fs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPlugin, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources } from './utils'
 | 
					 | 
				
			||||||
import { interfaces } from './interfaces'
 | 
					import { interfaces } from './interfaces'
 | 
				
			||||||
import { getConfigLoader } from './config'
 | 
					import { getConfigLoader } from './config'
 | 
				
			||||||
 | 
					import { getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata } from './utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Thread = Java.type('java.lang.Thread')
 | 
					const Thread = Java.type('java.lang.Thread')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,27 +25,53 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    private EventManager: event.Event
 | 
					    private EventManager: event.Event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private initialized: boolean = false
 | 
					    private initialized: boolean = false
 | 
				
			||||||
    private pluginRequireMap: Map<string, any>
 | 
					
 | 
				
			||||||
    private pluginInstanceMap: Map<string, plugin.Plugin>
 | 
					    private sacnnerMap: Map<string, plugin.PluginScanner>
 | 
				
			||||||
    private pluginMetadataMap: Map<string, plugin.PluginMetadata>
 | 
					    private loaderMap: Map<string, plugin.PluginLoader>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private instanceMap: Map<string, plugin.Plugin>
 | 
				
			||||||
 | 
					    private metadataMap: Map<string, plugin.PluginMetadata>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.sacnnerMap = new Map()
 | 
				
			||||||
 | 
					        this.loaderMap = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.instanceMap = new Map()
 | 
				
			||||||
 | 
					        this.metadataMap = new Map()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialize() {
 | 
					    initialize() {
 | 
				
			||||||
        if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
 | 
					        if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
 | 
				
			||||||
        if (this.initialized !== true) {
 | 
					        if (this.initialized !== true) {
 | 
				
			||||||
            console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
 | 
					            console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
 | 
				
			||||||
            console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType })
 | 
					            console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType })
 | 
				
			||||||
            this.pluginRequireMap = new Map()
 | 
					            let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
 | 
				
			||||||
            this.pluginInstanceMap = new Map()
 | 
					            pluginScanner.forEach((scanner) => {
 | 
				
			||||||
            this.pluginMetadataMap = getPluginSources()
 | 
					                console.debug(`loading plugin sacnner ${scanner.type}...`)
 | 
				
			||||||
 | 
					                this.sacnnerMap.set(scanner.type, scanner)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            let pluginLoaders = this.container.getAll<plugin.PluginLoader>(plugin.PluginLoader)
 | 
				
			||||||
 | 
					            pluginLoaders.forEach((loader) => {
 | 
				
			||||||
 | 
					                console.debug(`loading plugin loader ${loader.type}...`)
 | 
				
			||||||
 | 
					                this.loaderMap.set(loader.type, loader)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
            this.initialized = true
 | 
					            this.initialized = true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scan(folder: string): void {
 | 
					    scan(folder: string): void {
 | 
				
			||||||
 | 
					        if (!folder) { throw new Error('plugin scan folder can\'t be empty!') }
 | 
				
			||||||
        this.initialize()
 | 
					        this.initialize()
 | 
				
			||||||
        var plugin = fs.file(root, folder)
 | 
					        for (const [, scanner] of this.sacnnerMap) {
 | 
				
			||||||
        var files = this.scanFolder(plugin)
 | 
					            try {
 | 
				
			||||||
        this.loadPlugins(files)
 | 
					                scanner.scan(folder).forEach(file => {
 | 
				
			||||||
 | 
					                    this.loadPlugin(file, scanner)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            } catch (error) {
 | 
				
			||||||
 | 
					                console.error(`plugin scanner ${scanner.type} occurred error ${error}`)
 | 
				
			||||||
 | 
					                console.ex(error)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    build(): void {
 | 
					    build(): void {
 | 
				
			||||||
@@ -57,24 +83,45 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private runPluginStage(plugin: plugin.Plugin, stage: string, ext: Function) {
 | 
					    private runPluginStage(plugin: plugin.Plugin, stage: string, ext: Function) {
 | 
				
			||||||
 | 
					        if (!plugin) { throw new Error(`can't run runPluginStage ${stage} because plugin is ${plugin}`) }
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
					            this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
				
			||||||
            ext()
 | 
					            ext()
 | 
				
			||||||
            this.runCatch(plugin, stage)
 | 
					            this.runCatch(plugin, stage)
 | 
				
			||||||
            this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
					            this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
				
			||||||
            this.execPluginStage(plugin, stage)
 | 
					            plugin.description.loader[stage](plugin)
 | 
				
			||||||
        } catch (ex) {
 | 
					        } catch (ex) {
 | 
				
			||||||
            console.i18n("ms.plugin.manager.stage.exec.error", { plugin: plugin.description.name, executor: stage, error: ex })
 | 
					            console.i18n("ms.plugin.manager.stage.exec.error", { plugin: plugin.description.name, executor: stage, error: ex })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private loadPlugin(file: string, scanner: plugin.PluginScanner) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            let requireInstance = scanner.load(file)
 | 
				
			||||||
 | 
					            for (const [, loader] of this.loaderMap) {
 | 
				
			||||||
 | 
					                let metadata = loader.require(file, requireInstance)
 | 
				
			||||||
 | 
					                if (metadata && metadata.source && metadata.name) {
 | 
				
			||||||
 | 
					                    metadata.loader = loader
 | 
				
			||||||
 | 
					                    this.metadataMap.set(metadata.name, metadata)
 | 
				
			||||||
 | 
					                    return metadata
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.initialize.error", { name: file, ex: error })
 | 
				
			||||||
 | 
					            console.ex(error)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.console(`§efile §b${file} §ccan't load metadata. §eskip load!`)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 从文件加载插件
 | 
					     * 从文件加载插件
 | 
				
			||||||
     * @param file java.io.File
 | 
					     * @param file java.io.File
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    loadFromFile(file: string): plugin.Plugin {
 | 
					    loadFromFile(file: string, scanner = this.sacnnerMap.get('file')): plugin.Plugin {
 | 
				
			||||||
        let metadata = this.loadPlugin(file)
 | 
					        if (!file) { throw new Error('plugin file can\'t be null!') }
 | 
				
			||||||
        let plugin = this.buildPlugin(metadata && metadata.description ? metadata.description : this.pluginMetadataMap.get(file.toString()))
 | 
					        if (!scanner) { throw new Error('plugin scanner can\'t be null!') }
 | 
				
			||||||
 | 
					        let metadata = this.loadPlugin(file, scanner)
 | 
				
			||||||
 | 
					        let plugin = metadata.loader.build(metadata)
 | 
				
			||||||
        this.load(plugin)
 | 
					        this.load(plugin)
 | 
				
			||||||
        this.enable(plugin)
 | 
					        this.enable(plugin)
 | 
				
			||||||
        return plugin
 | 
					        return plugin
 | 
				
			||||||
@@ -110,16 +157,16 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    reload(...args: any[]): void {
 | 
					    reload(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
 | 
				
			||||||
            this.disable(pl)
 | 
					            this.disable(pl)
 | 
				
			||||||
            this.loadFromFile(pl.description.source)
 | 
					            this.loadFromFile(pl.description.source, pl.description.scanner)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getPlugin(name: string) {
 | 
					    getPlugin(name: string) {
 | 
				
			||||||
        return this.pluginInstanceMap.get(name)
 | 
					        return this.instanceMap.get(name)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getPlugins() {
 | 
					    getPlugins() {
 | 
				
			||||||
        return this.pluginInstanceMap
 | 
					        return this.instanceMap
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private runCatch(pl: any, func: string) {
 | 
					    private runCatch(pl: any, func: string) {
 | 
				
			||||||
@@ -132,64 +179,13 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private checkAndGet(name: string | plugin.Plugin | undefined | any): Map<string, plugin.Plugin> | plugin.Plugin[] {
 | 
					    private checkAndGet(name: string | plugin.Plugin | undefined | any): Map<string, plugin.Plugin> | plugin.Plugin[] {
 | 
				
			||||||
        if (name == this.pluginInstanceMap) { return this.pluginInstanceMap }
 | 
					        if (name == this.instanceMap) { return this.instanceMap }
 | 
				
			||||||
        if (typeof name == 'string' && this.pluginInstanceMap.has(name)) { return [this.pluginInstanceMap.get(name)] }
 | 
					        if (typeof name == 'string' && this.instanceMap.has(name)) { return [this.instanceMap.get(name)] }
 | 
				
			||||||
        if (name instanceof interfaces.Plugin) { return [name as plugin.Plugin] }
 | 
					        if (name instanceof interfaces.Plugin) { return [name as plugin.Plugin] }
 | 
				
			||||||
        if (name.description || name.description.name) { return [name as plugin.Plugin] }
 | 
					        if (name.description || name.description.name) { return [name as plugin.Plugin] }
 | 
				
			||||||
        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
					        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private scanFolder(folder: any): string[] {
 | 
					 | 
				
			||||||
        var files = []
 | 
					 | 
				
			||||||
        console.i18n('ms.plugin.manager.scan', { folder })
 | 
					 | 
				
			||||||
        this.checkUpdateFolder(folder)
 | 
					 | 
				
			||||||
        // must check file is exist maybe is a illegal symbolic link file
 | 
					 | 
				
			||||||
        fs.list(folder).forEach((file: any) => file.toFile().exists() ? files.push(file.toFile()) : void 0)
 | 
					 | 
				
			||||||
        return files
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 更新插件
 | 
					 | 
				
			||||||
     * @param path
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private checkUpdateFolder(path: any) {
 | 
					 | 
				
			||||||
        var update = fs.file(path, "update")
 | 
					 | 
				
			||||||
        if (!update.exists()) {
 | 
					 | 
				
			||||||
            update.mkdirs()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private loadPlugins(files: any[]): void {
 | 
					 | 
				
			||||||
        this.loadJsPlugins(files)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * JS类型插件预加载
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    private loadJsPlugins(files: any[]) {
 | 
					 | 
				
			||||||
        files.filter(file => file.name.endsWith(".js")).forEach(file => {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                this.loadPlugin(file)
 | 
					 | 
				
			||||||
            } catch (ex) {
 | 
					 | 
				
			||||||
                console.i18n("ms.plugin.manager.initialize.error", { name: file.name, ex })
 | 
					 | 
				
			||||||
                console.ex(ex)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private loadPlugin(file: any) {
 | 
					 | 
				
			||||||
        this.updatePlugin(file)
 | 
					 | 
				
			||||||
        return this.createPlugin(file.toString())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private updatePlugin(file: any) {
 | 
					 | 
				
			||||||
        var update = fs.file(fs.file(file.parentFile, 'update'), file.name)
 | 
					 | 
				
			||||||
        if (update.exists()) {
 | 
					 | 
				
			||||||
            console.i18n("ms.plugin.manager.build.update", { name: file.name })
 | 
					 | 
				
			||||||
            fs.move(update, file, true)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private allowProcess(servers: string[]) {
 | 
					    private allowProcess(servers: string[]) {
 | 
				
			||||||
        // Not set servers -> allow
 | 
					        // Not set servers -> allow
 | 
				
			||||||
        if (!servers || !servers.length) return true
 | 
					        if (!servers || !servers.length) return true
 | 
				
			||||||
@@ -203,59 +199,14 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private createPlugin(file: string) {
 | 
					 | 
				
			||||||
        //@ts-ignore
 | 
					 | 
				
			||||||
        let instance = require(file, { cache: false })
 | 
					 | 
				
			||||||
        this.pluginRequireMap.set(file, instance)
 | 
					 | 
				
			||||||
        return instance
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private buildPlugins() {
 | 
					    private buildPlugins() {
 | 
				
			||||||
        let metadatas = []
 | 
					        for (const [, metadata] of this.metadataMap) {
 | 
				
			||||||
        let pluginMetadatas = getPluginMetadatas()
 | 
					 | 
				
			||||||
        for (const [_, metadata] of pluginMetadatas) { metadatas.push(metadata) }
 | 
					 | 
				
			||||||
        for (const [_, instance] of this.pluginRequireMap) { if (instance.description) { this.buildPlugin(instance.description) } }
 | 
					 | 
				
			||||||
        for (const metadata of metadatas) {
 | 
					 | 
				
			||||||
            if (!this.allowProcess(metadata.servers)) { continue }
 | 
					 | 
				
			||||||
            this.buildPlugin(metadata)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private buildPlugin(metadata: interfaces.PluginMetadata) {
 | 
					 | 
				
			||||||
            let pluginInstance: plugin.Plugin
 | 
					            let pluginInstance: plugin.Plugin
 | 
				
			||||||
        switch (metadata.type) {
 | 
					            if (!this.loaderMap.has(metadata.type)) {
 | 
				
			||||||
            case "ioc":
 | 
					                console.error(`§4无法加载插件 §c${metadata.name} §4请检查 §c${metadata.type} §4加载器是否正常启用!`)
 | 
				
			||||||
                try {
 | 
					                continue
 | 
				
			||||||
                    this.bindPlugin(metadata)
 | 
					 | 
				
			||||||
                    pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
					 | 
				
			||||||
                    if (!(pluginInstance instanceof interfaces.Plugin)) {
 | 
					 | 
				
			||||||
                        console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
 | 
					 | 
				
			||||||
                        return
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                } catch (ex) {
 | 
					            (pluginInstance = this.loaderMap.get(metadata.type).build(metadata)) && this.instanceMap.set(metadata.name, pluginInstance)
 | 
				
			||||||
                    console.i18n("ms.plugin.manager.initialize.error", { name: metadata.name, ex })
 | 
					 | 
				
			||||||
                    console.ex(ex)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
            case "basic":
 | 
					 | 
				
			||||||
                pluginInstance = this.pluginRequireMap.get(metadata.source.toString())
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                throw new Error('§4不支持的插件类型 请检查加载器是否正常启用!')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        pluginInstance && this.pluginInstanceMap.set(metadata.name, pluginInstance)
 | 
					 | 
				
			||||||
        return pluginInstance
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private bindPlugin(metadata: interfaces.PluginMetadata) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
					 | 
				
			||||||
            if (pluginInstance.description.source + '' !== metadata.source + '') {
 | 
					 | 
				
			||||||
                console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
 | 
					 | 
				
			||||||
        } catch{
 | 
					 | 
				
			||||||
            this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -331,18 +282,4 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
					    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
        this.EventManager.disable(pluginInstance)
 | 
					        this.EventManager.disable(pluginInstance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private execPluginStage(pluginInstance: plugin.Plugin, stageName: string) {
 | 
					 | 
				
			||||||
        let stages = getPluginStageMetadata(pluginInstance, stageName)
 | 
					 | 
				
			||||||
        for (const stage of stages) {
 | 
					 | 
				
			||||||
            if (!this.allowProcess(stage.servers)) { continue }
 | 
					 | 
				
			||||||
            console.i18n("ms.plugin.manager.stage.exec", { plugin: pluginInstance.description.name, name: stage.executor, stage: stageName, servers: stage.servers })
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                pluginInstance[stage.executor].apply(pluginInstance)
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                console.i18n("ms.plugin.manager.stage.exec.error", { plugin: pluginInstance.description.name, executor: stage.executor, error })
 | 
					 | 
				
			||||||
                console.ex(error)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								packages/plugin/src/scanner/file-scanner.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								packages/plugin/src/scanner/file-scanner.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import { plugin } from "@ccms/api"
 | 
				
			||||||
 | 
					import * as fs from '@ccms/common/dist/fs'
 | 
				
			||||||
 | 
					import { provideSingletonNamed } from "@ccms/container"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@provideSingletonNamed(plugin.PluginScanner, 'file')
 | 
				
			||||||
 | 
					export class JSFileScanner implements plugin.PluginScanner {
 | 
				
			||||||
 | 
					    type: string = 'file'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    scan(target: any): string[] {
 | 
				
			||||||
 | 
					        return this.scanFolder(fs.concat(root, target))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    load(file: string) {
 | 
				
			||||||
 | 
					        if (typeof file === "string") { return }
 | 
				
			||||||
 | 
					        this.updatePlugin(file)
 | 
				
			||||||
 | 
					        //@ts-ignore
 | 
				
			||||||
 | 
					        return require(file.toString(), { cache: false })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private scanFolder(folder: any): string[] {
 | 
				
			||||||
 | 
					        var files = []
 | 
				
			||||||
 | 
					        console.i18n('ms.plugin.manager.scan', { folder })
 | 
				
			||||||
 | 
					        this.checkUpdateFolder(folder)
 | 
				
			||||||
 | 
					        // must check file is exist maybe is a illegal symbolic link file
 | 
				
			||||||
 | 
					        fs.list(folder).forEach((path: any) => {
 | 
				
			||||||
 | 
					            let file = path.toFile()
 | 
				
			||||||
 | 
					            if (file.exists() && file.getName().endsWith(".js")) {
 | 
				
			||||||
 | 
					                files.push(file)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        return files
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private checkUpdateFolder(path: any) {
 | 
				
			||||||
 | 
					        var update = fs.file(path, "update")
 | 
				
			||||||
 | 
					        if (!update.exists()) {
 | 
				
			||||||
 | 
					            update.mkdirs()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private updatePlugin(file: any) {
 | 
				
			||||||
 | 
					        var update = fs.file(fs.file(file.parentFile, 'update'), file.name)
 | 
				
			||||||
 | 
					        if (update.exists()) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.build.update", { name: file.name })
 | 
				
			||||||
 | 
					            fs.move(update, file, true)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,78 +1,79 @@
 | 
				
			|||||||
 | 
					import { plugin } from '@ccms/api'
 | 
				
			||||||
import { interfaces } from './interfaces'
 | 
					import { interfaces } from './interfaces'
 | 
				
			||||||
import { METADATA_KEY } from './constants'
 | 
					import { METADATA_KEY } from './constants'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pluginSourceCache = new Map<string, interfaces.PluginMetadata>();
 | 
					const pluginSourceCache = new Map<string, plugin.PluginMetadata>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPlugins() {
 | 
					function getPlugins() {
 | 
				
			||||||
    return [...getPluginMetadatas().values()].map((target) => target.target);
 | 
					    return [...getPluginMetadatas().values()].map((target) => target.target)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPlugin(name: string) {
 | 
					function getPlugin(name: string) {
 | 
				
			||||||
    return getPluginMetadatas().get(name);
 | 
					    return getPluginMetadatas().get(name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginSources() {
 | 
					function getPluginSources() {
 | 
				
			||||||
    let pluginSources: Map<string, interfaces.PluginMetadata> = Reflect.getMetadata(
 | 
					    let pluginSources: Map<string, plugin.PluginMetadata> = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.souece,
 | 
					        METADATA_KEY.souece,
 | 
				
			||||||
        Reflect
 | 
					        Reflect
 | 
				
			||||||
    ) || pluginSourceCache;
 | 
					    ) || pluginSourceCache
 | 
				
			||||||
    return pluginSources;
 | 
					    return pluginSources
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginMetadatas() {
 | 
					function getPluginMetadatas() {
 | 
				
			||||||
    let pluginMetadatas: Map<string, interfaces.PluginMetadata> = Reflect.getMetadata(
 | 
					    let pluginMetadatas: Map<string, plugin.PluginMetadata> = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.plugin,
 | 
					        METADATA_KEY.plugin,
 | 
				
			||||||
        Reflect
 | 
					        Reflect
 | 
				
			||||||
    ) || new Map<string, interfaces.PluginMetadata>();
 | 
					    ) || new Map<string, plugin.PluginMetadata>()
 | 
				
			||||||
    return pluginMetadatas;
 | 
					    return pluginMetadatas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginMetadata(target: any) {
 | 
					function getPluginMetadata(target: any) {
 | 
				
			||||||
    let pluginMetadata: interfaces.PluginMetadata = Reflect.getMetadata(
 | 
					    let pluginMetadata: plugin.PluginMetadata = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.plugin,
 | 
					        METADATA_KEY.plugin,
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || {};
 | 
					    ) || {}
 | 
				
			||||||
    return pluginMetadata;
 | 
					    return pluginMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginCommandMetadata(target: any) {
 | 
					function getPluginCommandMetadata(target: any) {
 | 
				
			||||||
    let commandMetadata: Map<string, interfaces.CommandMetadata> = Reflect.getMetadata(
 | 
					    let commandMetadata: Map<string, interfaces.CommandMetadata> = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.cmd,
 | 
					        METADATA_KEY.cmd,
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || new Map<string, interfaces.CommandMetadata>();
 | 
					    ) || new Map<string, interfaces.CommandMetadata>()
 | 
				
			||||||
    return commandMetadata;
 | 
					    return commandMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginTabCompleterMetadata(target: any) {
 | 
					function getPluginTabCompleterMetadata(target: any) {
 | 
				
			||||||
    let tabcompleterMetadata: Map<string, interfaces.CommandMetadata> = Reflect.getMetadata(
 | 
					    let tabcompleterMetadata: Map<string, interfaces.CommandMetadata> = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.tab,
 | 
					        METADATA_KEY.tab,
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || new Map<string, interfaces.CommandMetadata>();
 | 
					    ) || new Map<string, interfaces.CommandMetadata>()
 | 
				
			||||||
    return tabcompleterMetadata;
 | 
					    return tabcompleterMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginListenerMetadata(target: any) {
 | 
					function getPluginListenerMetadata(target: any) {
 | 
				
			||||||
    let listnerMetadata: interfaces.ListenerMetadata[] = Reflect.getMetadata(
 | 
					    let listnerMetadata: interfaces.ListenerMetadata[] = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.listener,
 | 
					        METADATA_KEY.listener,
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || [];
 | 
					    ) || []
 | 
				
			||||||
    return listnerMetadata;
 | 
					    return listnerMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginConfigMetadata(target: any) {
 | 
					function getPluginConfigMetadata(target: any) {
 | 
				
			||||||
    let configMetadata: Map<string, interfaces.ConfigMetadata> = Reflect.getMetadata(
 | 
					    let configMetadata: Map<string, interfaces.ConfigMetadata> = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.config,
 | 
					        METADATA_KEY.config,
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || new Map<string, interfaces.ConfigMetadata>();
 | 
					    ) || new Map<string, interfaces.ConfigMetadata>()
 | 
				
			||||||
    return configMetadata;
 | 
					    return configMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPluginStageMetadata(target: any, stage: string) {
 | 
					function getPluginStageMetadata(target: any, stage: string) {
 | 
				
			||||||
    let stageMetadata: interfaces.ExecMetadata[] = Reflect.getMetadata(
 | 
					    let stageMetadata: interfaces.ExecMetadata[] = Reflect.getMetadata(
 | 
				
			||||||
        METADATA_KEY.stage[stage],
 | 
					        METADATA_KEY.stage[stage],
 | 
				
			||||||
        target.constructor
 | 
					        target.constructor
 | 
				
			||||||
    ) || [];
 | 
					    ) || []
 | 
				
			||||||
    return stageMetadata;
 | 
					    return stageMetadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export {
 | 
					export {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user