Updated to fetch from git-based directory with index.json
This commit is contained in:
107
package-lock.json
generated
Normal file
107
package-lock.json
generated
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"name": "@pluginhost/core",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "@pluginhost/core",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { readdir, readFile, mkdir } from 'fs/promises';
|
import { readdir, readFile, mkdir } from 'fs/promises';
|
||||||
import { join, resolve } from 'path';
|
import { join, resolve, dirname } from 'path';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin Host - Manages plugin lifecycle and provides plugin API
|
* Plugin Host - Manages plugin lifecycle and provides plugin API
|
||||||
*/
|
*/
|
||||||
@@ -11,7 +15,10 @@ export class PluginHost extends EventEmitter {
|
|||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
super();
|
super();
|
||||||
this.directoryUrl = options.directoryUrl;
|
this.directoryUrl = options.directoryUrl;
|
||||||
this.pluginsDir = resolve(options.pluginsDir || './plugins');
|
// Resolve relative to the PluginHost.js file location (src/), then go up one level
|
||||||
|
this.pluginsDir = options.pluginsDir ?
|
||||||
|
(options.pluginsDir.startsWith('.') ? resolve(__dirname, '..', options.pluginsDir) : resolve(options.pluginsDir))
|
||||||
|
: resolve(__dirname, '../plugins');
|
||||||
this.autoUpdate = options.autoUpdate ?? true;
|
this.autoUpdate = options.autoUpdate ?? true;
|
||||||
this.updateInterval = options.updateInterval || 300000;
|
this.updateInterval = options.updateInterval || 300000;
|
||||||
|
|
||||||
@@ -42,18 +49,32 @@ export class PluginHost extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
async updateRegistry() {
|
async updateRegistry() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(this.directoryUrl);
|
// First fetch the index to get the list of available plugins
|
||||||
if (!response.ok) {
|
const indexUrl = `${this.directoryUrl}/index.json`;
|
||||||
console.warn('Failed to fetch plugin registry:', response.statusText);
|
const indexResponse = await fetch(indexUrl);
|
||||||
|
|
||||||
|
if (!indexResponse.ok) {
|
||||||
|
console.warn('Failed to fetch plugin index:', indexResponse.statusText);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = await response.text();
|
const index = await indexResponse.json();
|
||||||
const pluginFiles = this._parseDirectoryListing(html);
|
const pluginIds = index.plugins || [];
|
||||||
|
|
||||||
for (const file of pluginFiles) {
|
console.log(`Found ${pluginIds.length} plugins in directory`);
|
||||||
if (file.endsWith('.json')) {
|
|
||||||
await this._fetchPluginDefinition(file);
|
// Fetch each plugin definition
|
||||||
|
for (const pluginId of pluginIds) {
|
||||||
|
const pluginUrl = `${this.directoryUrl}/${pluginId}.json`;
|
||||||
|
try {
|
||||||
|
const response = await fetch(pluginUrl);
|
||||||
|
if (response.ok) {
|
||||||
|
const plugin = await response.json();
|
||||||
|
this.pluginRegistry.set(plugin.id, plugin);
|
||||||
|
console.log(` ✓ ${plugin.name} v${plugin.version}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(` ✗ Could not fetch ${pluginId}:`, error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/index.js
15
src/index.js
@@ -3,11 +3,22 @@ import { PluginHost } from './PluginHost.js';
|
|||||||
const host = new PluginHost({
|
const host = new PluginHost({
|
||||||
directoryUrl: 'http://synbox.ruv.wtf:8418/litruv/Plugin-Directory/raw/branch/main/plugins',
|
directoryUrl: 'http://synbox.ruv.wtf:8418/litruv/Plugin-Directory/raw/branch/main/plugins',
|
||||||
pluginsDir: './plugins',
|
pluginsDir: './plugins',
|
||||||
autoUpdate: true,
|
autoUpdate: true, // Auto-fetch registry updates
|
||||||
updateInterval: 300000 // 5 minutes
|
updateInterval: 300000 // 5 minutes
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('🔌 Initializing Plugin Host...\n');
|
||||||
|
|
||||||
await host.initialize();
|
await host.initialize();
|
||||||
await host.loadPlugins();
|
await host.loadPlugins();
|
||||||
|
|
||||||
console.log('Plugin Host initialized with plugins:', host.getLoadedPlugins().map(p => p.name));
|
console.log('\n📊 Plugin Host Status:');
|
||||||
|
console.log('====================');
|
||||||
|
console.log('Loaded plugins:', host.getLoadedPlugins().map(p => `${p.name} v${p.version}`).join(', ') || 'none');
|
||||||
|
console.log('Plugin directory:', host.pluginsDir);
|
||||||
|
console.log('\n📦 Available in Registry:', host.getRegistry().length);
|
||||||
|
host.getRegistry().forEach(p => {
|
||||||
|
console.log(` - ${p.name} v${p.version} (${p.id})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('\n✨ Plugin Host ready!');
|
||||||
|
|||||||
Reference in New Issue
Block a user