UNPKG

harmony-plugin-manager

Version:

A comprehensive TypeScript library for generating harmonious color palettes with WCAG 2.1 accessibility compliance

624 lines 22.4 kB
/** * Plugin Manager Builder - Fluent configuration and composition API * * The PluginManagerBuilder provides a fluent, expressive API for configuring * complex plugin arrangements. It's designed to make plugin management more * readable and maintainable, especially for large applications with many plugins. * * ## Key Benefits * * - **Fluent Interface**: Method chaining for readable configuration * - **Conditional Logic**: Runtime decisions about plugin inclusion * - **Grouping**: Organize related plugins with shared tags * - **Priority Management**: Easy priority assignment and ordering * - **Validation**: Pre-build validation of plugin configuration * - **Cloning**: Create variations of plugin configurations * * ## Usage Patterns * * ### Basic Building * ```typescript * const manager = createPluginBuilder<string, string>() * .plugin(validationPlugin) * .plugin(transformPlugin) * .plugin(outputPlugin) * .build(); * ``` * * ### Environment-Specific Configuration * ```typescript * const builder = createPluginBuilder<ApiRequest, ApiResponse>() * .plugin(corePlugin) * .when(isDevelopment, debugPlugin) * .when(isProduction, monitoringPlugin) * .group({ * tag: 'validation', * items: [ * { plugin: authPlugin, settings: { priority: 100 } }, * { plugin: inputValidationPlugin, settings: { priority: 90 } } * ] * }); * ``` */ import type { IPlugin } from '../core/interfaces'; import type { PluginContext, PluginSettings } from '../core/types'; import { PluginManager } from '../manager'; export declare class PluginManagerBuilder<TInput = unknown, TOutput = unknown, TMetadata extends Record<string, unknown> = Record<string, unknown>> { private readonly manager; /** * Registers a single plugin with optional settings * * This is the fundamental building block for plugin registration. * Each call adds one plugin to the manager's execution pipeline. * * @param plugin - Plugin instance to register * @param settings - Optional plugin configuration settings * * @returns Builder instance for method chaining * * @example * ```typescript * // Simple plugin registration * const builder = createPluginBuilder<string, string>() * .plugin(uppercasePlugin) * .plugin(trimPlugin); * ``` * * @example * ```typescript * // Plugin registration with detailed settings * const builder = createPluginBuilder<UserData, ProcessedUser>() * .plugin(validationPlugin, { * enabled: true, * priority: 100, * config: { * strictMode: true, * requiredFields: ['id', 'email'], * customValidators: ['email-format', 'phone-format'] * } * }) * .plugin(enrichmentPlugin, { * priority: 50, * config: { * dataSources: ['user-preferences', 'activity-history'], * cacheEnabled: true, * cacheTtl: 300000 // 5 minutes * } * }); * ``` * * @example * ```typescript * // Chained registration with different plugin types * const apiBuilder = createPluginBuilder<ApiRequest, ApiResponse>() * .plugin(rateLimitingPlugin, { * priority: 100, * config: { maxRequests: 1000, windowMs: 60000 } * }) * .plugin(authenticationPlugin, { * priority: 90, * config: { tokenExpiry: 3600, refreshEnabled: true } * }) * .plugin(businessLogicPlugin, { * priority: 50, * config: { enableCaching: true, enableAudit: true } * }) * .plugin(responseFormatterPlugin, { * priority: 10, * config: { includeMetadata: true, compression: 'gzip' } * }); * ``` */ plugin(plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>, settings?: Partial<PluginSettings>): this; /** * Registers multiple plugins with their respective settings * * Convenient method for bulk plugin registration when you have * multiple plugins to register at once. Particularly useful for * plugin suites or when loading plugins from configuration. * * @param plugins - Array of plugin configurations * * @returns Builder instance for method chaining * * @example * ```typescript * // Bulk registration of related plugins * const validationSuite = [ * { plugin: schemaValidationPlugin, settings: { priority: 100 } }, * { plugin: businessRuleValidationPlugin, settings: { priority: 90 } }, * { plugin: securityValidationPlugin, settings: { priority: 80 } } * ]; * * const builder = createPluginBuilder<ApiRequest, ApiResponse>() * .plugins(validationSuite) * .plugin(mainBusinessLogicPlugin); * ``` * * @example * ```typescript * // Configuration-driven plugin loading * const pluginConfigs = await loadPluginConfiguration(); * * const pluginRegistrations = pluginConfigs.map(config => ({ * plugin: pluginRegistry.get(config.name), * settings: { * enabled: config.enabled, * priority: config.priority, * config: config.parameters * } * })); * * const builder = createPluginBuilder<DataRecord, ProcessedRecord>() * .plugins(pluginRegistrations) * .plugin(outputPlugin); // Always include output plugin * ``` * * @example * ```typescript * // Environment-specific plugin suites * const developmentPlugins = [ * { plugin: debugPlugin, settings: { priority: 200 } }, * { plugin: performanceMonitorPlugin, settings: { priority: 190 } }, * { plugin: requestLoggerPlugin, settings: { priority: 180 } } * ]; * * const productionPlugins = [ * { plugin: metricsPlugin, settings: { priority: 200 } }, * { plugin: alertingPlugin, settings: { priority: 190 } }, * { plugin: auditPlugin, settings: { priority: 180 } } * ]; * * const builder = createPluginBuilder<UserRequest, UserResponse>() * .plugin(corePlugin) // Always include core functionality * .plugins(isDevelopment ? developmentPlugins : productionPlugins); * ``` */ plugins(plugins: Array<{ plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>; settings?: Partial<PluginSettings>; }>): this; /** * Conditionally registers a plugin based on a boolean condition * * Conditional registration allows you to include or exclude plugins * based on runtime conditions such as environment variables, * feature flags, configuration settings, or user preferences. * * @param condition - Whether to register the plugin (true = register) * @param plugin - Plugin to register if condition is true * @param settings - Optional plugin settings * * @returns Builder instance for method chaining * * @example * ```typescript * // Environment-based conditional registration * const isDevelopment = process.env.NODE_ENV === 'development'; * const isProduction = process.env.NODE_ENV === 'production'; * const enableDebug = process.env.DEBUG === 'true'; * * const builder = createPluginBuilder<ApiRequest, ApiResponse>() * .plugin(corePlugin) // Always include * * // Development-only plugins * .when(isDevelopment, debugPlugin) * .when(isDevelopment, mockDataPlugin) * .when(isDevelopment && enableDebug, verboseLoggingPlugin) * * // Production-only plugins * .when(isProduction, performanceMonitoringPlugin) * .when(isProduction, alertingPlugin) * .when(isProduction, compressionPlugin); * ``` * * @example * ```typescript * // Feature flag-driven registration * const featureFlags = await loadFeatureFlags(); * * const builder = createPluginBuilder<UserData, ProcessedUser>() * .plugin(basicProcessingPlugin) * * // Feature-specific plugins * .when(featureFlags.enableRecommendations, recommendationPlugin) * .when(featureFlags.enableAnalytics, analyticsPlugin) * .when(featureFlags.enablePersonalization, personalizationPlugin, { * config: { * algorithm: featureFlags.personalizationAlgorithm, * maxRecommendations: featureFlags.maxRecommendations * } * }) * * // Beta features * .when(featureFlags.betaFeatures && featureFlags.enableAI, aiProcessingPlugin); * ``` * * @example * ```typescript * // User preference-based registration * const userPreferences = await loadUserPreferences(userId); * const subscription = await getUserSubscription(userId); * * const builder = createPluginBuilder<UserContent, ProcessedContent>() * .plugin(basicContentPlugin) * * // Preference-based plugins * .when(userPreferences.enablePersonalization, personalizationPlugin) * .when(userPreferences.enableNotifications, notificationPlugin) * .when(userPreferences.privacyMode === false, analyticsPlugin) * * // Subscription-based features * .when(subscription.tier === 'premium', premiumFeaturesPlugin) * .when(subscription.tier === 'enterprise', enterpriseFeaturesPlugin) * .when(subscription.addOns.includes('advanced-analytics'), advancedAnalyticsPlugin); * ``` */ when(condition: boolean, plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>, settings?: Partial<PluginSettings>): this; /** * Registers a group of plugins with a common tag * * Plugin grouping helps organize related plugins and makes it easier * to manage plugin suites that work together. All plugins in a group * will be tagged with the group's tag, making them easy to query and * manage as a unit. * * @param plugins - Group configuration with tag and plugin items * * @returns Builder instance for method chaining * * @example * ```typescript * // Validation plugin group * const builder = createPluginBuilder<UserData, ProcessedUser>() * .group({ * tag: 'validation', * items: [ * { * plugin: schemaValidationPlugin, * settings: { * priority: 100, * config: { strictMode: true } * } * }, * { * plugin: businessRuleValidationPlugin, * settings: { * priority: 90, * config: { enableCustomRules: true } * } * }, * { * plugin: securityValidationPlugin, * settings: { * priority: 80, * config: { enableThreatDetection: true } * } * } * ] * }); * * // Later, you can query validation plugins: * // const validationPlugins = manager.getPluginsByTag('validation'); * ``` * * @example * ```typescript * // Multiple functional groups * const apiBuilder = createPluginBuilder<ApiRequest, ApiResponse>() * * // Security group * .group({ * tag: 'security', * items: [ * { plugin: authenticationPlugin, settings: { priority: 100 } }, * { plugin: authorizationPlugin, settings: { priority: 90 } }, * { plugin: rateLimitingPlugin, settings: { priority: 80 } } * ] * }) * * // Processing group * .group({ * tag: 'processing', * items: [ * { plugin: validationPlugin, settings: { priority: 70 } }, * { plugin: transformationPlugin, settings: { priority: 60 } }, * { plugin: businessLogicPlugin, settings: { priority: 50 } } * ] * }) * * // Output group * .group({ * tag: 'output', * items: [ * { plugin: formattingPlugin, settings: { priority: 20 } }, * { plugin: compressionPlugin, settings: { priority: 10 } }, * { plugin: cachePlugin, settings: { priority: 5 } } * ] * }); * ``` * * @example * ```typescript * // Environment-specific groups * const monitoringPlugins = isDevelopment * ? [ * { plugin: debugPlugin, settings: { priority: 200 } }, * { plugin: performancePlugin, settings: { priority: 190 } } * ] * : [ * { plugin: metricsPlugin, settings: { priority: 200 } }, * { plugin: alertingPlugin, settings: { priority: 190 } }, * { plugin: auditPlugin, settings: { priority: 180 } } * ]; * * const builder = createPluginBuilder<DataRecord, ProcessedRecord>() * .plugin(corePlugin) * .group({ * tag: 'monitoring', * items: monitoringPlugins * }); * ``` */ group(plugins: { tag: string; items: Array<{ plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>; settings?: Partial<PluginSettings>; }>; }): this; /** * Registers a plugin with a specific priority * * Priority assignment determines the order of plugin execution within * dependency levels. Higher priority plugins execute before lower priority * ones. This method provides a convenient way to set priority without * manually constructing settings objects. * * @param priority - Execution priority (higher = earlier execution) * @param plugin - Plugin to register * @param settings - Optional additional settings * * @returns Builder instance for method chaining * * @example * ```typescript * // Clear priority-based ordering * const builder = createPluginBuilder<ApiRequest, ApiResponse>() * // Critical early processing (100-90) * .withPriority(100, authenticationPlugin) * .withPriority(95, rateLimitingPlugin) * .withPriority(90, authorizationPlugin) * * // Validation and preprocessing (80-60) * .withPriority(80, inputValidationPlugin) * .withPriority(70, sanitizationPlugin) * .withPriority(60, normalizationPlugin) * * // Core business logic (50-30) * .withPriority(50, businessLogicPlugin) * .withPriority(40, dataEnrichmentPlugin) * .withPriority(30, calculationPlugin) * * // Output processing (20-10) * .withPriority(20, responseFormattingPlugin) * .withPriority(15, compressionPlugin) * .withPriority(10, cachePlugin); * ``` * * @example * ```typescript * // Priority with additional configuration * const builder = createPluginBuilder<UserData, ProcessedUser>() * .withPriority(100, validationPlugin, { * config: { * strictMode: true, * failFast: true, * requiredFields: ['id', 'email'] * } * }) * .withPriority(50, enrichmentPlugin, { * config: { * sources: ['database', 'cache', 'external-api'], * timeout: 5000, * fallbackEnabled: true * } * }) * .withPriority(10, outputPlugin, { * config: { * format: 'json', * includeMetadata: true, * compression: 'gzip' * } * }); * ``` * * @example * ```typescript * // Dynamic priority assignment * const config = await loadConfiguration(); * * const builder = createPluginBuilder<DataRecord, ProcessedRecord>() * .plugin(corePlugin); // Default priority (0) * * // Add plugins with computed priorities * config.plugins.forEach((pluginConfig, index) => { * const plugin = pluginRegistry.get(pluginConfig.name); * const priority = config.basePriority + (config.plugins.length - index) * 10; * * builder.withPriority(priority, plugin, { * enabled: pluginConfig.enabled, * config: pluginConfig.settings * }); * }); * ``` */ withPriority(priority: number, plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>, settings?: Partial<PluginSettings>): this; /** * Registers a plugin in disabled state * * Disabled plugins are registered but won't execute until explicitly enabled. * This is useful for plugins that you want to configure but activate later, * or for plugins that should only run under specific conditions. * * @param plugin - Plugin to register as disabled * @param settings - Optional additional settings * * @returns Builder instance for method chaining * * @example * ```typescript * // Register plugins that will be enabled conditionally later * const builder = createPluginBuilder<UserRequest, UserResponse>() * .plugin(corePlugin) // Always enabled * * // Disabled by default, enabled based on user tier * .disabled(premiumFeaturesPlugin, { * priority: 50, * config: { featureSet: 'premium' } * }) * .disabled(enterpriseFeaturesPlugin, { * priority: 40, * config: { featureSet: 'enterprise' } * }); * * // Later, before building, conditionally enable * const userTier = await getUserTier(userId); * if (userTier === 'premium') { * manager.configure('premium-features-plugin', { enabled: true }); * } else if (userTier === 'enterprise') { * manager.configure('enterprise-features-plugin', { enabled: true }); * } * ``` * * @example * ```typescript * // Feature flags with disabled plugins * const builder = createPluginBuilder<DataRecord, ProcessedRecord>() * .plugin(basicProcessingPlugin) * * // Register experimental features as disabled * .disabled(experimentalAlgorithmPlugin, { * priority: 60, * config: { algorithm: 'ml-enhanced', version: 'beta' } * }) * .disabled(advancedAnalyticsPlugin, { * priority: 30, * config: { realTimeProcessing: true } * }); * * // Enable based on feature flags * const featureFlags = await loadFeatureFlags(); * const manager = builder.build(); * * if (featureFlags.enableExperimental) { * manager.configure('experimental-algorithm-plugin', { enabled: true }); * } * if (featureFlags.enableAdvancedAnalytics) { * manager.configure('advanced-analytics-plugin', { enabled: true }); * } * ``` */ disabled(plugin: IPlugin<TInput, TOutput, PluginContext<TMetadata>>, settings?: Partial<PluginSettings>): this; /** * Builds and returns the configured plugin manager * * Building finalizes the plugin configuration and creates a ready-to-use * plugin manager. This process includes dependency resolution, execution * order determination, and pipeline construction. After building, the * manager cannot be reconfigured. * * @returns Built plugin manager ready for execution * * @throws {Error} When dependency resolution fails * @throws {Error} When circular dependencies are detected * * @example * ```typescript * // Basic build * const manager = createPluginBuilder<string, string>() * .plugin(validationPlugin) * .plugin(transformPlugin) * .plugin(outputPlugin) * .build(); // Now ready for execution * * const result = await manager.execute('input data', {}); * ``` * * @example * ```typescript * // Build with error handling * try { * const manager = createPluginBuilder<ApiRequest, ApiResponse>() * .plugin(authPlugin) * .plugin(businessLogicPlugin, { dependencies: ['auth-plugin'] }) * .plugin(responsePlugin, { dependencies: ['business-logic-plugin'] }) * .validate() // Optional: validate before building * .build(); * * console.log('Manager built successfully'); * * } catch (error) { * console.error('Build failed:', error.message); * // Handle build failure * } * ``` */ build(): PluginManager<TInput, TOutput, TMetadata>; /** * Validates the current builder configuration * * Validation checks the current plugin configuration for common issues * before building. This can help catch configuration problems early * and provide better error messages. * * @returns Builder instance for method chaining * * @throws {Error} When validation fails * * @example * ```typescript * // Validate before building * const manager = createPluginBuilder<UserData, ProcessedUser>() * .plugin(validationPlugin) * .plugin(transformPlugin) * .validate() // Throws if no plugins or other issues * .build(); * ``` */ validate(): this; /** * Creates a deep copy of the current builder configuration * * Cloning allows you to create variations of plugin configurations * without modifying the original builder. This is useful for creating * different configurations for different environments or use cases. * * @returns New builder instance with identical configuration * * @example * ```typescript * // Base configuration * const baseBuilder = createPluginBuilder<ApiRequest, ApiResponse>() * .plugin(authPlugin) * .plugin(validationPlugin) * .plugin(businessLogicPlugin); * * // Development variant * const devBuilder = baseBuilder.clone() * .plugin(debugPlugin) * .plugin(mockDataPlugin); * * // Production variant * const prodBuilder = baseBuilder.clone() * .plugin(monitoringPlugin) * .plugin(alertingPlugin) * .plugin(compressionPlugin); * * const devManager = devBuilder.build(); * const prodManager = prodBuilder.build(); * ``` */ clone(): PluginManagerBuilder<TInput, TOutput, TMetadata>; } //# sourceMappingURL=plugin-builder.d.ts.map