Plugin Development Guide

Learn how to develop, use, and manage plugins in XyPriss.

Plugin System Overview

XyPriss features an extensible plugin system that allows you to:

  • Add custom functionality to your server
  • Extend core features
  • Create reusable components
  • Integrate third-party services
  • Implement custom middleware and routes

Plugin Interface

interface Plugin {
    name: string;
    version: string;
    description?: string;
    dependencies?: string[];
    
    initialize(context: PluginContext): Promise;
    execute(context: PluginContext): Promise;
    cleanup?(): Promise;
}

interface PluginContext {
    app: Express;
    server: XyPrissServer;
    config: PluginConfig;
    logger: Logger;
    cache: CacheManager;
    metrics: PerformanceManager;
}

Creating a Custom Plugin

Basic Plugin Structure

import { Plugin, PluginContext } from "xypriss";

export class MyCustomPlugin implements Plugin {
    name = "my-custom-plugin";
    version = "1.0.0";
    description = "A custom plugin for XyPriss";
    
    async initialize(context: PluginContext): Promise {
        context.logger.info(`Initializing ${this.name} v${this.version}`);
        
        // Plugin initialization logic
        // Set up routes, middleware, etc.
    }
    
    async execute(context: PluginContext): Promise {
        // Main plugin execution logic
        return { status: "success" };
    }
    
    async cleanup(): Promise {
        // Cleanup logic when server shuts down
        console.log(`Cleaning up ${this.name}`);
    }
}

Example: Database Connection Plugin

import { Plugin, PluginContext } from "xypriss";
import { Pool } from "pg";

export class DatabasePlugin implements Plugin {
    name = "database-connection";
    version = "1.0.0";
    description = "PostgreSQL database connection plugin";
    
    private pool: Pool | null = null;
    
    async initialize(context: PluginContext): Promise {
        const { config, logger } = context;
        
        // Create database connection pool
        this.pool = new Pool({
            host: config.options.host || "localhost",
            port: config.options.port || 5432,
            database: config.options.database,
            user: config.options.user,
            password: config.options.password,
            max: config.options.maxConnections || 20
        });
        
        // Test connection
        try {
            const client = await this.pool.connect();
            await client.query("SELECT NOW()");
            client.release();
            logger.info("Database connection established");
        } catch (error) {
            logger.error("Database connection failed:", error);
            throw error;
        }
        
        // Add database to context
        (context.app as any).db = this.pool;
    }
    
    async execute(context: PluginContext): Promise {
        // Add health check route
        context.app.get("/health/database", async (req, res) => {
            try {
                const client = await this.pool!.connect();
                const result = await client.query("SELECT NOW() as timestamp");
                client.release();
                
                res.json({
                    status: "healthy",
                    timestamp: result.rows[0].timestamp
                });
            } catch (error) {
                res.status(503).json({
                    status: "unhealthy",
                    error: error.message
                });
            }
        });
        
        return { status: "database plugin active" };
    }
    
    async cleanup(): Promise {
        if (this.pool) {
            await this.pool.end();
            console.log("Database connections closed");
        }
    }
}

Using Plugins

Plugin Configuration

import { createServer } from "xypriss";
import { DatabasePlugin } from "./plugins/DatabasePlugin";
import { AuthenticationPlugin } from "./plugins/AuthenticationPlugin";

const server = createServer({
    plugins: [
        {
            name: "database-connection",
            plugin: new DatabasePlugin(),
            enabled: true,
            options: {
                host: "localhost",
                port: 5432,
                database: "myapp",
                user: "dbuser",
                password: "dbpassword",
                maxConnections: 20
            }
        },
        {
            name: "jwt-authentication",
            plugin: new AuthenticationPlugin(),
            enabled: true,
            options: {
                jwtSecret: process.env.JWT_SECRET
            }
        }
    ]
});

Plugin Lifecycle

  1. Loading Phase - Plugin files are loaded and instantiated
  2. Initialization Phase - initialize() method is called
  3. Execution Phase - execute() method is called
  4. Cleanup Phase - cleanup() method is called (if defined)

Plugin Dependencies

export class AdvancedPlugin implements Plugin {
    name = "advanced-plugin";
    version = "1.0.0";
    dependencies = ["database-connection", "jwt-authentication"];
    
    async initialize(context: PluginContext): Promise {
        // This plugin will only load after its dependencies
        const db = (context.app as any).db;
        const auth = (context.app as any).authenticateToken;
        
        if (!db || !auth) {
            throw new Error("Required dependencies not available");
        }
    }
}

Best Practices

Plugin Structure

  • Keep plugins focused on a single responsibility
  • Use clear, descriptive names
  • Include proper version information
  • Document plugin configuration options

Error Handling

  • Handle errors gracefully in all plugin methods
  • Provide meaningful error messages
  • Don't crash the entire server on plugin errors

Resource Management

  • Clean up resources in the cleanup() method
  • Close database connections, file handles, etc.
  • Remove event listeners and timers