import { isDev, logger } from "@certd/basic"; export type Registrable = { name: string; title: string; desc?: string; group?: string; deprecated?: string; order?: number; }; export type TargetGetter = () => Promise; export type RegistryItem = { define: Registrable; target: TargetGetter; }; export type OnRegisterContext = { registry: Registry; key: string; value: RegistryItem; }; export type OnRegister = (ctx: OnRegisterContext) => void; export class Registry { type = ""; storage: { [key: string]: RegistryItem; } = {}; onRegister?: OnRegister; onUnRegister?: OnRegister; constructor(type: string, onRegister?: OnRegister, onUnRegister?: OnRegister) { this.type = type; this.onRegister = onRegister; this.onUnRegister = onUnRegister; } register(key: string, value: RegistryItem) { if (!key || value == null) { return; } this.storage[key] = value; if (this.onRegister) { this.onRegister({ registry: this, key, value, }); } logger.info(`注册插件:${this.type}:${key}`); } unRegister(key: string) { if (this.onUnRegister) { this.onUnRegister({ registry: this, key, value: this.storage[key], }); } delete this.storage[key]; logger.info(`反注册插件:${this.type}:${key}`); } get(name: string): RegistryItem { if (!name) { throw new Error("插件名称不能为空"); } const plugin = this.storage[name]; if (!plugin) { throw new Error(`插件${name}还未注册`); } return plugin; } getStorage() { return this.storage; } getDefineList(prefix?: string) { let list = []; if (prefix) { prefix = prefix + ":"; } for (const key in this.storage) { if (prefix && !key.startsWith(prefix)) { continue; } const define = this.getDefine(key); if (define) { if (define?.deprecated) { continue; } if (!isDev() && define.name.startsWith("demo")) { continue; } list.push({ ...define, key }); } } list = list.sort((a, b) => { return (a.order ?? 10) - (b?.order ?? 10); }); return list; } getDefine(key: string, prefix?: string) { if (prefix) { key = prefix + ":" + key; } const item = this.storage[key]; if (!item) { return; } return item.define; } } export function createRegistry(type: string, onRegister?: OnRegister, onUnRegister?: OnRegister): Registry { const pipelineregistrycacheKey = "PIPELINE_REGISTRY_CACHE"; // @ts-ignore let cached: any = global[pipelineregistrycacheKey]; if (!cached) { cached = {}; // @ts-ignore global[pipelineregistrycacheKey] = cached; } if (cached[type]) { return cached[type]; } const newRegistry = new Registry(type, onRegister, onUnRegister); cached[type] = newRegistry; return newRegistry; }