commit 23cfbee2bcc80cb4b1b94c30791bf3e1022dbd49 Author: Max Litruv Boonzaayer Date: Fri Apr 17 01:48:23 2026 +1000 Initial commit: Example plugin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..552f221 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1a1f8c --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# Example Plugin + +A demonstration plugin showing how to build plugins for the Plugin Host system. + +## Features + +This example demonstrates: + +- ✅ Plugin activation/deactivation lifecycle +- ✅ Hook registration and execution +- ✅ Event listening and emission +- ✅ Configuration access +- ✅ Logging utilities +- ✅ Periodic tasks +- ✅ Exported functions + +## Structure + +``` +Plugin-Example/ +├── plugin.json # Plugin manifest +├── index.js # Main plugin code +├── package.json # NPM metadata +└── README.md # This file +``` + +## Plugin Manifest (`plugin.json`) + +The manifest defines your plugin's metadata: + +```json +{ + "id": "example-plugin", + "name": "Example Plugin", + "version": "1.0.0", + "description": "An example plugin", + "author": "Your Name", + "main": "index.js", + "repository": "http://your-git-repo", + "config": { + "greeting": "Hello from Example Plugin!" + }, + "permissions": ["hooks", "events"] +} +``` + +## Plugin API + +### Lifecycle Methods + +```javascript +export async function activate(context) { + // Called when plugin loads +} + +export async function deactivate(context) { + // Called when plugin unloads +} +``` + +### Context API + +```javascript +context.registerHook(hookName, callback) // Register a hook +context.runHook(hookName, ...args) // Execute hooks +context.getConfig(key) // Get config value +context.log(...args) // Log with plugin prefix +context.on(event, listener) // Listen to events +context.emit(event, ...args) // Emit events +``` + +## Creating Your Own Plugin + +1. Copy this example +2. Edit `plugin.json` with your plugin details +3. Implement `activate()` and `deactivate()` in `index.js` +4. Add any additional functions/features +5. Submit to the Plugin Directory + +## Hooks + +This example registers: +- `on-startup` - Called when the system starts +- `transform-data` - Transform data objects + +## License + +MIT diff --git a/index.js b/index.js new file mode 100644 index 0000000..88badb5 --- /dev/null +++ b/index.js @@ -0,0 +1,85 @@ +/** + * Example Plugin - Demonstrates plugin capabilities + * + * This plugin shows: + * - Activation/Deactivation lifecycle + * - Hook registration and execution + * - Event handling + * - Configuration access + * - Logging + */ + +let intervalId = null; + +/** + * Called when the plugin is loaded + * @param {Object} context - Plugin context API + */ +export async function activate(context) { + context.log('Plugin activated!'); + + const greeting = context.getConfig('greeting'); + context.log(greeting); + + // Register a hook that other plugins or the host can call + context.registerHook('on-startup', async () => { + context.log('Startup hook called!'); + return { status: 'ready', plugin: 'example-plugin' }; + }); + + // Register a data transformation hook + context.registerHook('transform-data', async (data) => { + context.log('Transforming data:', data); + return { + ...data, + processedBy: 'example-plugin', + timestamp: new Date().toISOString() + }; + }); + + // Listen to host events + context.on('plugin-loaded', (plugin) => { + context.log(`Another plugin was loaded: ${plugin.name}`); + }); + + // Example: Periodic task + intervalId = setInterval(() => { + context.log('Periodic task running...'); + }, 30000); // Every 30 seconds + + // Example: Run a hook that other plugins might listen to + const results = await context.runHook('example-event', { message: 'Hello!' }); + context.log('Hook results:', results); +} + +/** + * Called when the plugin is unloaded + * @param {Object} context - Plugin context API + */ +export async function deactivate(context) { + context.log('Plugin deactivating...'); + + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + } + + context.log('Plugin deactivated!'); +} + +/** + * Example exported function that can be called directly + */ +export function doSomething(data) { + console.log('doSomething called with:', data); + return { success: true, data }; +} + +/** + * Example async function + */ +export async function fetchData(url) { + console.log('Fetching data from:', url); + // In a real plugin, you might fetch from an API + return { data: 'example data', url }; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0d5164d --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "@pluginhost/example", + "version": "1.0.0", + "description": "Example plugin for the plugin host system", + "main": "index.js", + "type": "module", + "keywords": ["plugin", "example"], + "author": "", + "license": "MIT" +} diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..d833540 --- /dev/null +++ b/plugin.json @@ -0,0 +1,16 @@ +{ + "id": "example-plugin", + "name": "Example Plugin", + "version": "1.0.0", + "description": "An example plugin demonstrating the plugin system capabilities", + "author": "Your Name", + "main": "index.js", + "repository": "http://synbox.ruv.wtf:8418/litruv/Plugin-Example.git", + "config": { + "greeting": "Hello from Example Plugin!" + }, + "permissions": [ + "hooks", + "events" + ] +}