mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 18:10:18 +05:30
76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
class PluginLoader {
|
|
/**
|
|
* @param {string[]} searchDirs - Directories to scan for plugin folders
|
|
*/
|
|
constructor(searchDirs = []) {
|
|
this.searchDirs = searchDirs;
|
|
this.loadedIds = new Set();
|
|
}
|
|
|
|
/**
|
|
* Discover plugins by scanning searchDirs for manifest.json files.
|
|
* Returns array of { id, name, version, description, manifest, PluginClass, dir }
|
|
*/
|
|
discoverPlugins() {
|
|
const plugins = [];
|
|
for (const dir of this.searchDirs) {
|
|
if (!fs.existsSync(dir)) continue;
|
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
for (const entry of entries) {
|
|
if (!entry.isDirectory()) continue;
|
|
const pluginDir = path.join(dir, entry.name);
|
|
const manifestPath = path.join(pluginDir, 'manifest.json');
|
|
if (!fs.existsSync(manifestPath)) continue;
|
|
try {
|
|
const raw = fs.readFileSync(manifestPath, 'utf-8');
|
|
const manifest = JSON.parse(raw);
|
|
this.validateManifest(manifest);
|
|
let PluginClass = null;
|
|
const indexPath = path.join(pluginDir, 'index.js');
|
|
if (fs.existsSync(indexPath)) {
|
|
try {
|
|
const loaded = require(indexPath);
|
|
PluginClass = loaded.Plugin || loaded.default || null;
|
|
} catch (err) {
|
|
console.error(`[PluginLoader] Failed to load index.js for "${manifest.id}":`, err.message);
|
|
continue;
|
|
}
|
|
}
|
|
plugins.push({
|
|
id: manifest.id,
|
|
name: manifest.name,
|
|
version: manifest.version,
|
|
description: manifest.description,
|
|
manifest,
|
|
PluginClass,
|
|
dir: pluginDir
|
|
});
|
|
this.loadedIds.add(manifest.id);
|
|
} catch (err) {
|
|
console.error(`[PluginLoader] Skipping plugin in ${pluginDir}:`, err.message);
|
|
}
|
|
}
|
|
}
|
|
return plugins;
|
|
}
|
|
|
|
/**
|
|
* Validate a manifest object. Throws on invalid.
|
|
*/
|
|
validateManifest(manifest) {
|
|
if (!manifest.id) throw new Error('Manifest missing required field: id');
|
|
if (!manifest.name) throw new Error('Manifest missing required field: name');
|
|
if (!manifest.version) throw new Error('Manifest missing required field: version');
|
|
if (!manifest.description) throw new Error('Manifest missing required field: description');
|
|
if (this.loadedIds.has(manifest.id)) {
|
|
throw new Error(`Duplicate plugin id: "${manifest.id}"`);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
module.exports = { PluginLoader };
|