fix: #1574 & Clear CJS cache and reload plugins on install

Add support for clearing CommonJS module cache when unloading plugins and reload plugins on install. PluginLoader now uses createRequire to access require.cache and exposes clearCache(pluginPath) to remove cached modules under the plugin directory; plugin manager calls this when unloading. Web UI backend install handlers now reload an existing plugin (with progress updates) instead of skipping registration, ensuring updated code/metadata take effect.
This commit is contained in:
手瓜一十雪 2026-02-02 14:14:06 +08:00
parent 9b385ac9c9
commit 82a7154b92
3 changed files with 36 additions and 6 deletions

View File

@ -179,6 +179,9 @@ export class OB11PluginMangerAdapter extends IOB11NetworkAdapter<PluginConfig> i
this.pluginRouters.delete(entry.id);
}
// 清理模块缓存
this.loader.clearCache(entry.pluginPath);
// 重置状态
entry.loaded = false;
entry.runtime = {

View File

@ -1,5 +1,7 @@
import fs from 'fs';
import path from 'path';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import { LogWrapper } from 'napcat-core/helper/log';
import {
PluginPackageJson,
@ -295,4 +297,24 @@ export class PluginLoader {
return null;
}
/**
* require
* CJS
*/
clearCache (pluginPath: string): void {
try {
// 规范化路径以确保匹配正确
const normalizedPluginPath = path.resolve(pluginPath);
// 遍历缓存并删除属于该插件目录的模块
Object.keys(require.cache).forEach((id) => {
if (id.startsWith(normalizedPluginPath)) {
delete require.cache[id];
this.logger.logDebug(`[PluginLoader] Cleared cache for: ${id}`);
}
});
} catch (e) {
this.logger.logError('[PluginLoader] Error clearing module cache:', e);
}
}
}

View File

@ -254,11 +254,13 @@ export const InstallPluginFromStoreHandler: RequestHandler = async (req, res) =>
// 删除临时文件
fs.unlinkSync(tempZipPath);
// 如果 pluginManager 存在,立即注册插件
// 如果 pluginManager 存在,立即注册或重载插件
const pluginManager = getPluginManager();
if (pluginManager) {
// 检查是否已注册,避免重复注册
if (!pluginManager.getPluginInfo(id)) {
// 如果插件已存在,则重载以刷新版本信息;否则注册新插件
if (pluginManager.getPluginInfo(id)) {
await pluginManager.reloadPlugin(id);
} else {
await pluginManager.loadPluginById(id);
}
}
@ -336,11 +338,14 @@ export const InstallPluginFromStoreSSEHandler: RequestHandler = async (req, res)
sendProgress('解压完成,正在清理...', 90);
fs.unlinkSync(tempZipPath);
// 如果 pluginManager 存在,立即注册插件
// 如果 pluginManager 存在,立即注册或重载插件
const pluginManager = getPluginManager();
if (pluginManager) {
// 检查是否已注册,避免重复注册
if (!pluginManager.getPluginInfo(id)) {
// 如果插件已存在,则重载以刷新版本信息;否则注册新插件
if (pluginManager.getPluginInfo(id)) {
sendProgress('正在刷新插件信息...', 95);
await pluginManager.reloadPlugin(id);
} else {
sendProgress('正在注册插件...', 95);
await pluginManager.loadPluginById(id);
}