fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
340 lines (336 loc) • 12.4 kB
JavaScript
'use strict';
var events = require('events');
var index = require('../../../../components/fortified-function/index.js');
var PluginTypes = require('./types/PluginTypes.js');
/**
* Ultra-Fast Plugin Registry
*
* Central registry for managing plugins with <0.1ms registration overhead
* and intelligent lifecycle management for optimal performance.
*/
/**
* Ultra-fast plugin registry with intelligent management
*/
class PluginRegistry extends events.EventEmitter {
constructor(cache, cluster, config) {
super();
this.plugins = new Map();
this.pluginsByType = new Map();
this.pluginStats = new Map();
this.isInitialized = false;
// Performance optimization: Pre-sorted plugin arrays by priority
this.sortedPluginCache = new Map();
this.lastCacheUpdate = 0;
this.CACHE_TTL = 5000; // 5 seconds
this.cache = cache;
this.cluster = cluster;
this.config = {
maxPlugins: 100,
enableHotReload: true,
enableProfiling: true,
performanceThresholds: {
maxExecutionTime: 10, // 10ms max
maxMemoryUsage: 50 * 1024 * 1024, // 50MB
maxCpuUsage: 80, // 80%
},
...config,
};
this.logger = this.createLogger();
this.initializePluginTypes();
}
/**
* Initialize plugin type maps for ultra-fast lookups
*/
initializePluginTypes() {
Object.values(PluginTypes.PluginType).forEach((type) => {
this.pluginsByType.set(type, []);
this.sortedPluginCache.set(type, []);
});
}
/**
* Create optimized logger for plugin operations
*/
createLogger() {
const fortifiedLogger = index.func((level, message, data) => {
new Date().toISOString();
if (level === "error") {
console.error(`[PluginRegistry] ${message}`, data);
}
else if (level === "warn") {
console.warn(`[PluginRegistry] ${message}`, data);
}
else if (level === "debug" &&
process.env.NODE_ENV === "development") {
console.debug(`[PluginRegistry] ${message}`, data);
}
else {
console.log(`[PluginRegistry] ${message}`, data);
}
}, { ultraFast: "maximum", auditLog: false });
return {
debug: (message, data) => fortifiedLogger("debug", message, data),
info: (message, data) => fortifiedLogger("info", message, data),
warn: (message, data) => fortifiedLogger("warn", message, data),
error: (message, error) => fortifiedLogger("error", message, error),
performance: (pluginId, executionTime) => {
if (this.config.enableProfiling) {
fortifiedLogger("performance", `Plugin ${pluginId} executed in ${executionTime}ms`);
}
},
};
}
/**
* Register a plugin with ultra-fast registration (<0.1ms)
*/
async register(plugin) {
const startTime = performance.now();
try {
// Validate plugin
this.validatePlugin(plugin);
// Check if plugin already exists
if (this.plugins.has(plugin.id)) {
throw new Error(`Plugin ${plugin.id} is already registered`);
}
// Check plugin limit
if (this.plugins.size >= this.config.maxPlugins) {
throw new Error(`Maximum plugin limit (${this.config.maxPlugins}) reached`);
}
// Initialize plugin if needed
if (plugin.initialize) {
const initContext = {
cache: this.cache,
cluster: this.cluster,
config: {
maxExecutionTime: plugin.maxExecutionTime,
enableProfiling: this.config.enableProfiling,
enableCaching: plugin.isCacheable,
enableEncryption: false,
enableAuditLogging: false,
securityLevel: "basic",
customSettings: {},
},
logger: this.logger,
};
await plugin.initialize(initContext);
}
// Precompile plugin if supported
if (plugin.precompile) {
await plugin.precompile();
}
// Register plugin
this.plugins.set(plugin.id, plugin);
// Add to type-specific collection
const typePlugins = this.pluginsByType.get(plugin.type) || [];
typePlugins.push(plugin);
this.pluginsByType.set(plugin.type, typePlugins);
// Initialize stats
this.pluginStats.set(plugin.id, {
pluginId: plugin.id,
executionCount: 0,
totalExecutionTime: 0,
averageExecutionTime: 0,
errorCount: 0,
lastExecuted: new Date(),
performanceScore: 100,
});
// Invalidate sorted cache
this.invalidateSortedCache();
const registrationTime = performance.now() - startTime;
this.logger.info(`Plugin ${plugin.id} registered in ${registrationTime.toFixed(3)}ms`);
// Emit event
this.emitPluginEvent(PluginTypes.PluginEventType.PLUGIN_REGISTERED, plugin.id, {
type: plugin.type,
priority: plugin.priority,
registrationTime,
});
}
catch (error) {
this.logger.error(`Failed to register plugin ${plugin.id}`, error);
throw error;
}
}
/**
* Unregister a plugin
*/
async unregister(pluginId) {
const plugin = this.plugins.get(pluginId);
if (!plugin) {
throw new Error(`Plugin ${pluginId} not found`);
}
try {
// Cleanup plugin if supported
if (plugin.cleanup) {
// Create minimal context for cleanup
const cleanupContext = {
pluginData: new Map(),
security: {
isAuthenticated: false,
roles: [],
permissions: [],
},
metrics: {
requestStartTime: Date.now(),
pluginExecutionTimes: new Map(),
cacheHits: 0,
cacheMisses: 0,
},
};
await plugin.cleanup(cleanupContext);
}
// Remove from collections
this.plugins.delete(pluginId);
this.pluginStats.delete(pluginId);
// Remove from type-specific collection
const typePlugins = this.pluginsByType.get(plugin.type) || [];
const filteredPlugins = typePlugins.filter((p) => p.id !== pluginId);
this.pluginsByType.set(plugin.type, filteredPlugins);
// Invalidate sorted cache
this.invalidateSortedCache();
this.logger.info(`Plugin ${pluginId} unregistered`);
// Emit event
this.emitPluginEvent(PluginTypes.PluginEventType.PLUGIN_UNREGISTERED, pluginId);
}
catch (error) {
this.logger.error(`Failed to unregister plugin ${pluginId}`, error);
throw error;
}
}
/**
* Get plugins by type with ultra-fast sorted lookup
*/
getPluginsByType(type) {
const now = Date.now();
// Check if cache is valid
if (now - this.lastCacheUpdate < this.CACHE_TTL) {
return this.sortedPluginCache.get(type) || [];
}
// Rebuild sorted cache
const plugins = this.pluginsByType.get(type) || [];
const sortedPlugins = plugins.sort((a, b) => a.priority - b.priority);
this.sortedPluginCache.set(type, sortedPlugins);
this.lastCacheUpdate = now;
return sortedPlugins;
}
/**
* Get plugin by ID
*/
getPlugin(pluginId) {
return this.plugins.get(pluginId);
}
/**
* Get all registered plugins
*/
getAllPlugins() {
return Array.from(this.plugins.values());
}
/**
* Get plugin execution statistics
*/
getPluginStats(pluginId) {
return this.pluginStats.get(pluginId);
}
/**
* Get all plugin statistics
*/
getAllStats() {
return Array.from(this.pluginStats.values());
}
/**
* Update plugin execution statistics
*/
updateStats(pluginId, executionTime, success) {
const stats = this.pluginStats.get(pluginId);
if (!stats)
return;
stats.executionCount++;
stats.totalExecutionTime += executionTime;
stats.averageExecutionTime =
stats.totalExecutionTime / stats.executionCount;
stats.lastExecuted = new Date();
if (!success) {
stats.errorCount++;
}
// Calculate performance score (0-100)
const errorRate = stats.errorCount / stats.executionCount;
const timeScore = Math.max(0, 100 - (stats.averageExecutionTime / 10) * 100);
const errorScore = Math.max(0, 100 - errorRate * 100);
stats.performanceScore = (timeScore + errorScore) / 2;
// Check performance thresholds
if (executionTime > this.config.performanceThresholds.maxExecutionTime) {
this.emitPluginEvent(PluginTypes.PluginEventType.PERFORMANCE_THRESHOLD_EXCEEDED, pluginId, {
executionTime,
threshold: this.config.performanceThresholds.maxExecutionTime,
});
}
}
/**
* Validate plugin before registration
*/
validatePlugin(plugin) {
if (!plugin.id || typeof plugin.id !== "string") {
throw new Error("Plugin must have a valid string ID");
}
if (!plugin.name || typeof plugin.name !== "string") {
throw new Error("Plugin must have a valid string name");
}
if (!plugin.version || typeof plugin.version !== "string") {
throw new Error("Plugin must have a valid string version");
}
if (!Object.values(PluginTypes.PluginType).includes(plugin.type)) {
throw new Error(`Invalid plugin type: ${plugin.type}`);
}
if (!Object.values(PluginTypes.PluginPriority).includes(plugin.priority)) {
throw new Error(`Invalid plugin priority: ${plugin.priority}`);
}
if (typeof plugin.execute !== "function") {
throw new Error("Plugin must have an execute method");
}
if (plugin.maxExecutionTime <= 0) {
throw new Error("Plugin maxExecutionTime must be positive");
}
}
/**
* Invalidate sorted plugin cache
*/
invalidateSortedCache() {
this.lastCacheUpdate = 0;
}
/**
* Emit plugin event
*/
emitPluginEvent(type, pluginId, data) {
const event = {
type,
pluginId,
timestamp: new Date(),
data,
};
this.emit(type, event);
}
/**
* Get registry statistics (ultra-fast optimized)
*/
getRegistryStats() {
const totalPlugins = this.plugins.size;
const pluginsByType = {};
let totalExecutions = 0;
let totalExecutionTime = 0;
// Ultra-fast: Only count plugins that actually exist (avoid iterating all enum values)
this.pluginsByType.forEach((plugins, type) => {
pluginsByType[type] = plugins.length;
});
// Ultra-fast: Single iteration through stats
this.pluginStats.forEach((stats) => {
totalExecutions += stats.executionCount;
totalExecutionTime += stats.totalExecutionTime;
});
return {
totalPlugins,
pluginsByType,
averageExecutionTime: totalExecutions > 0 ? totalExecutionTime / totalExecutions : 0,
totalExecutions,
};
}
}
exports.PluginRegistry = PluginRegistry;
//# sourceMappingURL=PluginRegistry.js.map