UNPKG

kist

Version:

Lightweight Package Pipeline Processor with Plugin Architecture

197 lines 8.57 kB
import { __awaiter } from "tslib"; import { existsSync, readdirSync, readFileSync, statSync } from "fs"; import { join } from "path"; import { AbstractProcess } from "../abstract/AbstractProcess.js"; export class PluginManager extends AbstractProcess { constructor() { super(); this.loadedPlugins = new Map(); this.pluginActions = new Map(); this.logInfo("PluginManager initialized."); } static getInstance() { if (!PluginManager.instance) { PluginManager.instance = new PluginManager(); } return PluginManager.instance; } static resetInstance() { PluginManager.instance = null; } discoverPlugins(options) { return __awaiter(this, void 0, void 0, function* () { this.logInfo("Starting plugin discovery..."); const prefixes = (options === null || options === void 0 ? void 0 : options.pluginPrefixes) || [ "@getkist/action-", "kist-plugin-", ]; yield this.discoverNpmPlugins(prefixes); if (options === null || options === void 0 ? void 0 : options.localPluginsPath) { yield this.discoverLocalPlugins(options.localPluginsPath); } this.logInfo(`Plugin discovery complete. Loaded ${this.loadedPlugins.size} plugins.`); }); } discoverNpmPlugins(prefixes) { return __awaiter(this, void 0, void 0, function* () { const nodeModulesPath = join(process.cwd(), "node_modules"); try { const directories = readdirSync(nodeModulesPath, { withFileTypes: true, }); for (const dir of directories) { if (dir.isDirectory() && dir.name.startsWith("@")) { yield this.discoverScopedPlugins(join(nodeModulesPath, dir.name), prefixes); } for (const prefix of prefixes) { if (dir.isDirectory() && !prefix.startsWith("@") && dir.name.startsWith(prefix)) { yield this.loadPlugin(join(nodeModulesPath, dir.name), dir.name); } } } } catch (error) { this.logError("Failed to discover npm plugins.", error); } }); } discoverScopedPlugins(scopePath, prefixes) { return __awaiter(this, void 0, void 0, function* () { try { const packages = readdirSync(scopePath, { withFileTypes: true }); for (const pkg of packages) { for (const prefix of prefixes) { const scopePrefix = prefix.split("/")[1]; const pkgPath = join(scopePath, pkg.name); const isDir = pkg.isDirectory() || (pkg.isSymbolicLink() && statSync(pkgPath).isDirectory()); if (isDir && scopePrefix && pkg.name.startsWith(scopePrefix)) { const fullName = `${scopePath.split("/").pop()}/${pkg.name}`; yield this.loadPlugin(join(scopePath, pkg.name), fullName); } } } } catch (_error) { this.logDebug(`No scoped plugins found in ${scopePath}`); } }); } discoverLocalPlugins(localPath) { return __awaiter(this, void 0, void 0, function* () { try { const pluginPath = join(process.cwd(), localPath); const directories = readdirSync(pluginPath, { withFileTypes: true, }); for (const dir of directories) { if (dir.isDirectory()) { yield this.loadPlugin(join(pluginPath, dir.name), `local:${dir.name}`); } } } catch (_error) { this.logDebug(`No local plugins found at ${localPath}`); } }); } loadPlugin(pluginPath, pluginName) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; try { this.logDebug(`Loading plugin: ${pluginName}`); let entryPoint = pluginPath; const packageJsonPath = join(pluginPath, "package.json"); if (existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); const mainEntry = packageJson.module || packageJson.main || ((_b = (_a = packageJson.exports) === null || _a === void 0 ? void 0 : _a["."]) === null || _b === void 0 ? void 0 : _b.import) || ((_d = (_c = packageJson.exports) === null || _c === void 0 ? void 0 : _c["."]) === null || _d === void 0 ? void 0 : _d.require) || ((_e = packageJson.exports) === null || _e === void 0 ? void 0 : _e["."]) || "dist/index.js"; entryPoint = join(pluginPath, mainEntry); } catch (jsonError) { this.logDebug(`Failed to parse package.json for ${pluginName}`); } } const pluginModule = yield import(entryPoint); const plugin = pluginModule.default || pluginModule; if (!plugin || typeof plugin.registerActions !== "function") { this.logWarn(`Plugin ${pluginName} does not implement ActionPlugin interface.`); return; } const metadata = { name: pluginName, version: typeof plugin.version === "string" ? plugin.version : "unknown", description: typeof plugin.description === "string" ? plugin.description : undefined, actions: [], }; const actions = plugin.registerActions(); for (const [actionName, actionClass] of Object.entries(actions)) { this.pluginActions.set(actionName, actionClass); metadata.actions.push(actionName); this.logDebug(` - Registered action: ${actionName}`); } this.loadedPlugins.set(pluginName, metadata); this.logInfo(`Plugin "${pluginName}" loaded successfully with ${metadata.actions.length} actions.`); } catch (error) { this.logError(`Failed to load plugin ${pluginName}:`, error); } }); } registerPlugin(plugin, name) { this.logInfo(`Manually registering plugin: ${name}`); const metadata = { name, version: typeof plugin.version === "string" ? plugin.version : "unknown", description: typeof plugin.description === "string" ? plugin.description : undefined, actions: [], }; const actions = plugin.registerActions(); for (const [actionName, actionClass] of Object.entries(actions)) { this.pluginActions.set(actionName, actionClass); metadata.actions.push(actionName); } this.loadedPlugins.set(name, metadata); this.logInfo(`Plugin "${name}" registered with ${metadata.actions.length} actions.`); } getPluginActions() { return new Map(this.pluginActions); } getLoadedPlugins() { return Array.from(this.loadedPlugins.values()); } getPluginMetadata(name) { return this.loadedPlugins.get(name); } isPluginLoaded(name) { return this.loadedPlugins.has(name); } listPluginActions() { return Array.from(this.pluginActions.keys()); } clearPlugins() { this.loadedPlugins.clear(); this.pluginActions.clear(); this.logInfo("All plugins cleared."); } } PluginManager.instance = null; //# sourceMappingURL=PluginManager.js.map