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
- Loading Phase - Plugin files are loaded and instantiated
- Initialization Phase -
initialize()
method is called - Execution Phase -
execute()
method is called - 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