mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2024-12-11 17:07:07 +01:00
Plugin cleanup and validation fixes
This commit is contained in:
parent
437a6c1f40
commit
ea85cfcbdd
12
server.js
12
server.js
@ -612,8 +612,10 @@ const setupTasks = async function () {
|
|||||||
|
|
||||||
const exitProcess = () => {
|
const exitProcess = () => {
|
||||||
statsEndpoint.onExit();
|
statsEndpoint.onExit();
|
||||||
|
if (typeof cleanupPlugins === 'function') {
|
||||||
|
cleanupPlugins();
|
||||||
|
}
|
||||||
process.exit();
|
process.exit();
|
||||||
cleanupPlugins();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up event listeners for a graceful shutdown
|
// Set up event listeners for a graceful shutdown
|
||||||
@ -636,13 +638,19 @@ const setupTasks = async function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads server plugins from a directory.
|
||||||
|
* @returns {Promise<Function>} Function to be run on server exit
|
||||||
|
*/
|
||||||
async function loadPlugins() {
|
async function loadPlugins() {
|
||||||
try {
|
try {
|
||||||
const pluginDirectory = path.join(serverDirectory, 'plugins');
|
const pluginDirectory = path.join(serverDirectory, 'plugins');
|
||||||
const loader = require('./src/plugin-loader');
|
const loader = require('./src/plugin-loader');
|
||||||
await loader.loadPlugins(app, pluginDirectory);
|
const cleanupPlugins = await loader.loadPlugins(app, pluginDirectory);
|
||||||
|
return cleanupPlugins;
|
||||||
} catch {
|
} catch {
|
||||||
console.log('Plugin loading failed.');
|
console.log('Plugin loading failed.');
|
||||||
|
return () => {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,22 +27,23 @@ const isESModule = (file) => path.extname(file) === '.mjs';
|
|||||||
*/
|
*/
|
||||||
async function loadPlugins(app, pluginsPath) {
|
async function loadPlugins(app, pluginsPath) {
|
||||||
const exitHooks = [];
|
const exitHooks = [];
|
||||||
|
const emptyFn = () => {};
|
||||||
|
|
||||||
// Server plugins are disabled.
|
// Server plugins are disabled.
|
||||||
if (!enableServerPlugins) {
|
if (!enableServerPlugins) {
|
||||||
return;
|
return emptyFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugins directory does not exist.
|
// Plugins directory does not exist.
|
||||||
if (!fs.existsSync(pluginsPath)) {
|
if (!fs.existsSync(pluginsPath)) {
|
||||||
return;
|
return emptyFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const files = fs.readdirSync(pluginsPath);
|
const files = fs.readdirSync(pluginsPath);
|
||||||
|
|
||||||
// No plugins to load.
|
// No plugins to load.
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
return;
|
return emptyFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@ -144,7 +145,7 @@ async function loadFromFile(app, pluginFilePath, exitHooks) {
|
|||||||
* @returns {boolean} True if the plugin ID is valid.
|
* @returns {boolean} True if the plugin ID is valid.
|
||||||
*/
|
*/
|
||||||
function isValidPluginID(id) {
|
function isValidPluginID(id) {
|
||||||
return /^[a-z0-9_-]$/.test(id);
|
return /^[a-z0-9_-]+$/.test(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +157,8 @@ function isValidPluginID(id) {
|
|||||||
* @returns {Promise<boolean>} Promise that resolves to true if plugin was initialized successfully
|
* @returns {Promise<boolean>} Promise that resolves to true if plugin was initialized successfully
|
||||||
*/
|
*/
|
||||||
async function initPlugin(app, plugin, exitHooks) {
|
async function initPlugin(app, plugin, exitHooks) {
|
||||||
if (typeof plugin.info !== 'object') {
|
const info = plugin.info || plugin.default?.info;
|
||||||
|
if (typeof info !== 'object') {
|
||||||
console.error('Failed to load plugin module; plugin info not found');
|
console.error('Failed to load plugin module; plugin info not found');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -164,7 +166,7 @@ async function initPlugin(app, plugin, exitHooks) {
|
|||||||
// We don't currently use "name" or "description" but it would be nice to have a UI for listing server plugins, so
|
// We don't currently use "name" or "description" but it would be nice to have a UI for listing server plugins, so
|
||||||
// require them now just to be safe
|
// require them now just to be safe
|
||||||
for (const field of ['id', 'name', 'description']) {
|
for (const field of ['id', 'name', 'description']) {
|
||||||
if (typeof plugin.info[field] !== 'string') {
|
if (typeof info[field] !== 'string') {
|
||||||
console.error(`Failed to load plugin module; plugin info missing field '${field}'`);
|
console.error(`Failed to load plugin module; plugin info missing field '${field}'`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -175,20 +177,21 @@ async function initPlugin(app, plugin, exitHooks) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = plugin.info;
|
const { id } = info;
|
||||||
|
|
||||||
if (!isValidPluginID(id)) {
|
if (!isValidPluginID(id)) {
|
||||||
console.error(`Failed to load plugin module; invalid plugin ID '${id}'`);
|
console.error(`Failed to load plugin module; invalid plugin ID '${id}'`);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow the plugin to register API routes under /plugins/[plugin ID] via a router
|
// Allow the plugin to register API routes under /api/plugins/[plugin ID] via a router
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
await plugin.init(router);
|
await plugin.init(router);
|
||||||
|
|
||||||
// Add API routes to the app if the plugin registered any
|
// Add API routes to the app if the plugin registered any
|
||||||
if (router.stack.length > 0) {
|
if (router.stack.length > 0) {
|
||||||
app.use(`/plugins/${id}`, router);
|
app.use(`/api/plugins/${id}`, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof plugin.exit === 'function') {
|
if (typeof plugin.exit === 'function') {
|
||||||
|
Loading…
Reference in New Issue
Block a user