timonel 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +323 -695
  3. package/dist/cli.js +275 -15
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.js +12 -0
  6. package/dist/lib/helm.d.ts +471 -0
  7. package/dist/lib/helm.js +483 -0
  8. package/dist/lib/helmChartWriter.d.ts +157 -0
  9. package/dist/lib/helmChartWriter.js +171 -1
  10. package/dist/lib/policy/configurationLoader.d.ts +132 -0
  11. package/dist/lib/policy/configurationLoader.js +132 -0
  12. package/dist/lib/policy/errorContextGenerator.d.ts +89 -0
  13. package/dist/lib/policy/errorContextGenerator.js +99 -2
  14. package/dist/lib/policy/errors.d.ts +35 -0
  15. package/dist/lib/policy/errors.js +36 -0
  16. package/dist/lib/policy/index.d.ts +9 -0
  17. package/dist/lib/policy/index.js +16 -0
  18. package/dist/lib/policy/parallelExecutor.d.ts +90 -0
  19. package/dist/lib/policy/parallelExecutor.js +86 -3
  20. package/dist/lib/policy/pluginLoader.d.ts +92 -0
  21. package/dist/lib/policy/pluginLoader.js +92 -1
  22. package/dist/lib/policy/pluginRegistry.d.ts +54 -0
  23. package/dist/lib/policy/pluginRegistry.js +56 -0
  24. package/dist/lib/policy/policyEngine.d.ts +137 -0
  25. package/dist/lib/policy/policyEngine.js +191 -5
  26. package/dist/lib/policy/resultAggregator.d.ts +46 -0
  27. package/dist/lib/policy/resultAggregator.js +69 -1
  28. package/dist/lib/policy/resultFormatter.d.ts +88 -0
  29. package/dist/lib/policy/resultFormatter.js +101 -0
  30. package/dist/lib/policy/types.d.ts +136 -0
  31. package/dist/lib/policy/types.js +8 -0
  32. package/dist/lib/policy/validationCache.d.ts +146 -0
  33. package/dist/lib/policy/validationCache.js +142 -6
  34. package/dist/lib/resources/baseResourceProvider.d.ts +45 -0
  35. package/dist/lib/resources/baseResourceProvider.js +48 -1
  36. package/dist/lib/resources/cloud/aws/awsResources.d.ts +192 -0
  37. package/dist/lib/resources/cloud/aws/awsResources.js +163 -1
  38. package/dist/lib/resources/cloud/aws/karpenterResources.d.ts +131 -0
  39. package/dist/lib/resources/cloud/aws/karpenterResources.js +77 -0
  40. package/dist/lib/rutter.d.ts +381 -3
  41. package/dist/lib/rutter.js +439 -28
  42. package/dist/lib/security.d.ts +123 -0
  43. package/dist/lib/security.js +162 -4
  44. package/dist/lib/templates/flexible-subchart.d.ts +52 -0
  45. package/dist/lib/templates/flexible-subchart.js +70 -0
  46. package/dist/lib/templates/umbrella-chart.d.ts +27 -0
  47. package/dist/lib/templates/umbrella-chart.js +89 -0
  48. package/dist/lib/types.d.ts +26 -0
  49. package/dist/lib/umbrella.d.ts +23 -0
  50. package/dist/lib/umbrella.js +23 -0
  51. package/dist/lib/umbrellaRutter.d.ts +75 -0
  52. package/dist/lib/umbrellaRutter.js +82 -2
  53. package/dist/lib/utils/envVarsLoader.d.ts +49 -0
  54. package/dist/lib/utils/envVarsLoader.js +53 -0
  55. package/dist/lib/utils/helmConstructSerializer.d.ts +17 -0
  56. package/dist/lib/utils/helmConstructSerializer.js +22 -0
  57. package/dist/lib/utils/helmControlStructures.d.ts +194 -0
  58. package/dist/lib/utils/helmControlStructures.js +180 -0
  59. package/dist/lib/utils/helmHelpers/envHelpers.d.ts +13 -0
  60. package/dist/lib/utils/helmHelpers/envHelpers.js +13 -0
  61. package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +13 -0
  62. package/dist/lib/utils/helmHelpers/gitopsHelpers.js +13 -0
  63. package/dist/lib/utils/helmHelpers/index.d.ts +74 -0
  64. package/dist/lib/utils/helmHelpers/index.js +85 -1
  65. package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +13 -0
  66. package/dist/lib/utils/helmHelpers/observabilityHelpers.js +13 -0
  67. package/dist/lib/utils/helmHelpers/types.d.ts +23 -0
  68. package/dist/lib/utils/helmHelpers/types.js +4 -0
  69. package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +13 -0
  70. package/dist/lib/utils/helmHelpers/validationHelpers.js +13 -0
  71. package/dist/lib/utils/helmHelpers.d.ts +62 -0
  72. package/dist/lib/utils/helmHelpers.js +77 -0
  73. package/dist/lib/utils/helmYamlSerializer.d.ts +77 -0
  74. package/dist/lib/utils/helmYamlSerializer.js +398 -21
  75. package/dist/lib/utils/logger.d.ts +153 -0
  76. package/dist/lib/utils/logger.js +170 -2
  77. package/dist/lib/utils/valuesRef.d.ts +181 -50
  78. package/dist/lib/utils/valuesRef.js +168 -170
  79. package/dist/lib/validation/inputValidator.d.ts +45 -0
  80. package/dist/lib/validation/inputValidator.js +67 -2
  81. package/dist/types/index.d.ts +34 -0
  82. package/dist/types/index.js +3 -0
  83. package/package.json +31 -38
@@ -1,41 +1,133 @@
1
+ /**
2
+ * Plugin Loader
3
+ *
4
+ * This module provides plugin discovery and loading capabilities for the policy engine.
5
+ * It supports loading plugins from npm packages, version compatibility checks, and
6
+ * conditional loading based on environment.
7
+ *
8
+ * @since 3.0.0
9
+ */
1
10
  import type { PolicyPlugin, PluginMetadata } from './types.js';
11
+ /**
12
+ * Plugin loading options
13
+ */
2
14
  export interface PluginLoaderOptions {
15
+ /** Base directory for plugin discovery */
3
16
  baseDirectory?: string;
17
+ /** Environment for conditional loading */
4
18
  environment?: string;
19
+ /** Whether to validate plugin compatibility */
5
20
  validateCompatibility?: boolean;
21
+ /** Supported Kubernetes versions for compatibility checks */
6
22
  supportedKubernetesVersions?: string[];
23
+ /** Plugin registry URL for discovery */
7
24
  registryUrl?: string;
25
+ /** Timeout for plugin loading operations */
8
26
  loadTimeout?: number;
9
27
  }
28
+ /**
29
+ * Plugin discovery result
30
+ */
10
31
  export interface PluginDiscoveryResult {
32
+ /** Plugin package name */
11
33
  packageName: string;
34
+ /** Plugin version */
12
35
  version: string;
36
+ /** Plugin metadata */
13
37
  metadata?: PluginMetadata;
38
+ /** Whether plugin is compatible */
14
39
  compatible: boolean;
40
+ /** Compatibility issues if any */
15
41
  compatibilityIssues?: string[];
42
+ /** Plugin source (npm, local, etc.) */
16
43
  source: 'npm' | 'local' | 'registry';
17
44
  }
45
+ /**
46
+ * Plugin loading result
47
+ */
18
48
  export interface PluginLoadingResult {
49
+ /** Loaded plugin instance */
19
50
  plugin: PolicyPlugin;
51
+ /** Plugin package name */
20
52
  packageName: string;
53
+ /** Loading source */
21
54
  source: 'npm' | 'local' | 'registry';
55
+ /** Loading time in milliseconds */
22
56
  loadTime: number;
57
+ /** Whether plugin passed validation */
23
58
  validated: boolean;
59
+ /** Validation warnings if any */
24
60
  warnings?: string[];
25
61
  }
62
+ /**
63
+ * Plugin loader for policy engine
64
+ */
26
65
  export declare class PluginLoader {
27
66
  private readonly options;
28
67
  private readonly logger;
29
68
  private readonly loadedPlugins;
30
69
  constructor(options?: PluginLoaderOptions);
70
+ /**
71
+ * Loads a plugin from an npm package
72
+ * @param packageName - NPM package name
73
+ * @param version - Optional version constraint
74
+ * @returns Plugin loading result
75
+ */
31
76
  loadFromPackage(packageName: string, version?: string): Promise<PluginLoadingResult>;
77
+ /**
78
+ * Discovers available plugins in the environment
79
+ * @param searchPattern - Optional search pattern for plugin names
80
+ * @returns Array of discovered plugins
81
+ */
32
82
  discoverPlugins(searchPattern?: string): Promise<PluginDiscoveryResult[]>;
83
+ /**
84
+ * Loads multiple plugins from a list of package names
85
+ * @param packages - Array of package names or package@version strings
86
+ * @returns Array of loading results
87
+ */
33
88
  loadMultiplePlugins(packages: string[]): Promise<PluginLoadingResult[]>;
89
+ /**
90
+ * Validates that a plugin implements the required interface
91
+ * @param plugin - Plugin to validate
92
+ * @param packageName - Package name for error reporting
93
+ * @throws {PluginRegistrationError} When plugin is invalid
94
+ */
34
95
  static validatePluginInterface(plugin: unknown, packageName: string): asserts plugin is PolicyPlugin;
96
+ /**
97
+ * Gets all loaded plugins
98
+ * @returns Array of loaded plugin results
99
+ */
35
100
  getLoadedPlugins(): PluginLoadingResult[];
101
+ /**
102
+ * Clears the plugin cache
103
+ */
36
104
  clearCache(): void;
105
+ /**
106
+ * Loads a module with timeout protection
107
+ * @param modulePath - Module path to load
108
+ * @returns Loaded plugin
109
+ * @private
110
+ */
37
111
  private loadModuleWithTimeout;
112
+ /**
113
+ * Validates plugin interface (instance method)
114
+ * @param plugin - Plugin to validate
115
+ * @param packageName - Package name for error reporting
116
+ * @private
117
+ */
38
118
  private validatePluginInterface;
119
+ /**
120
+ * Checks plugin compatibility with current environment
121
+ * @param plugin - Plugin to check
122
+ * @returns Array of compatibility issues
123
+ * @private
124
+ */
39
125
  private checkCompatibility;
126
+ /**
127
+ * Determines if plugin should be loaded in current environment
128
+ * @param _plugin - Plugin to check (unused for now)
129
+ * @returns True if plugin should be loaded
130
+ * @private
131
+ */
40
132
  private shouldLoadInEnvironment;
41
133
  }
@@ -1,14 +1,32 @@
1
+ /**
2
+ * Plugin Loader
3
+ *
4
+ * This module provides plugin discovery and loading capabilities for the policy engine.
5
+ * It supports loading plugins from npm packages, version compatibility checks, and
6
+ * conditional loading based on environment.
7
+ *
8
+ * @since 3.0.0
9
+ */
1
10
  import { createLogger } from '../utils/logger.js';
2
11
  import { PluginError, PluginRegistrationError } from './errors.js';
12
+ /**
13
+ * Constants for error messages
14
+ */
3
15
  const UNKNOWN_ERROR_MESSAGE = 'Unknown error';
16
+ /**
17
+ * Default plugin loader options
18
+ */
4
19
  const DEFAULT_LOADER_OPTIONS = {
5
20
  baseDirectory: process.cwd(),
6
21
  environment: 'development',
7
22
  validateCompatibility: true,
8
23
  supportedKubernetesVersions: ['1.25', '1.26', '1.27', '1.28', '1.29'],
9
24
  registryUrl: 'https://registry.npmjs.org',
10
- loadTimeout: 30000,
25
+ loadTimeout: 30000, // 30 seconds
11
26
  };
27
+ /**
28
+ * Plugin loader for policy engine
29
+ */
12
30
  export class PluginLoader {
13
31
  constructor(options = {}) {
14
32
  this.loadedPlugins = new Map();
@@ -19,6 +37,12 @@ export class PluginLoader {
19
37
  operation: 'plugin_loader_init',
20
38
  });
21
39
  }
40
+ /**
41
+ * Loads a plugin from an npm package
42
+ * @param packageName - NPM package name
43
+ * @param version - Optional version constraint
44
+ * @returns Plugin loading result
45
+ */
22
46
  async loadFromPackage(packageName, version) {
23
47
  const startTime = Date.now();
24
48
  this.logger.info('Loading plugin from package', {
@@ -27,6 +51,7 @@ export class PluginLoader {
27
51
  operation: 'load_from_package',
28
52
  });
29
53
  try {
54
+ // Check if already loaded
30
55
  const cacheKey = `${packageName}@${version || 'latest'}`;
31
56
  if (this.loadedPlugins.has(cacheKey)) {
32
57
  const cached = this.loadedPlugins.get(cacheKey);
@@ -37,14 +62,19 @@ export class PluginLoader {
37
62
  });
38
63
  return cached;
39
64
  }
65
+ // Construct module path
40
66
  const modulePath = version ? `${packageName}@${version}` : packageName;
67
+ // Load the module with timeout
41
68
  const plugin = await this.loadModuleWithTimeout(modulePath);
69
+ // Validate plugin interface
42
70
  this.validatePluginInterface(plugin, packageName);
71
+ // Check compatibility if enabled
43
72
  const warnings = [];
44
73
  if (this.options.validateCompatibility) {
45
74
  const compatibilityIssues = this.checkCompatibility(plugin);
46
75
  warnings.push(...compatibilityIssues);
47
76
  }
77
+ // Check environment conditions
48
78
  if (!this.shouldLoadInEnvironment(plugin)) {
49
79
  throw new PluginError(`Plugin '${packageName}' is not enabled for environment '${this.options.environment}'`, packageName);
50
80
  }
@@ -57,6 +87,7 @@ export class PluginLoader {
57
87
  validated: true,
58
88
  ...(warnings.length > 0 && { warnings }),
59
89
  };
90
+ // Cache the result
60
91
  this.loadedPlugins.set(cacheKey, result);
61
92
  this.logger.info('Plugin loaded successfully', {
62
93
  packageName,
@@ -80,6 +111,11 @@ export class PluginLoader {
80
111
  throw new PluginError(`Failed to load plugin from package '${packageName}': ${error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE}`, packageName, { originalError: error, loadTime });
81
112
  }
82
113
  }
114
+ /**
115
+ * Discovers available plugins in the environment
116
+ * @param searchPattern - Optional search pattern for plugin names
117
+ * @returns Array of discovered plugins
118
+ */
83
119
  async discoverPlugins(searchPattern) {
84
120
  this.logger.info('Discovering plugins', {
85
121
  searchPattern,
@@ -88,6 +124,9 @@ export class PluginLoader {
88
124
  });
89
125
  const discovered = [];
90
126
  try {
127
+ // For now, return empty array as actual discovery would require
128
+ // scanning node_modules, package.json, or registry API calls
129
+ // This is a placeholder for future implementation
91
130
  this.logger.info('Plugin discovery completed', {
92
131
  discoveredCount: discovered.length,
93
132
  operation: 'discovery_complete',
@@ -102,6 +141,11 @@ export class PluginLoader {
102
141
  throw new PluginError(`Plugin discovery failed: ${error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE}`, 'discovery');
103
142
  }
104
143
  }
144
+ /**
145
+ * Loads multiple plugins from a list of package names
146
+ * @param packages - Array of package names or package@version strings
147
+ * @returns Array of loading results
148
+ */
105
149
  async loadMultiplePlugins(packages) {
106
150
  this.logger.info('Loading multiple plugins', {
107
151
  packageCount: packages.length,
@@ -110,6 +154,7 @@ export class PluginLoader {
110
154
  });
111
155
  const results = [];
112
156
  const errors = [];
157
+ // Load plugins in parallel
113
158
  const loadPromises = packages.map(async (pkg) => {
114
159
  try {
115
160
  const [packageName, version] = pkg.includes('@') && !pkg.startsWith('@') ? pkg.split('@') : [pkg, undefined];
@@ -124,11 +169,13 @@ export class PluginLoader {
124
169
  }
125
170
  });
126
171
  const loadResults = await Promise.all(loadPromises);
172
+ // Collect successful results
127
173
  for (const result of loadResults) {
128
174
  if (result) {
129
175
  results.push(result);
130
176
  }
131
177
  }
178
+ // Log errors but don't throw (graceful degradation)
132
179
  if (errors.length > 0) {
133
180
  this.logger.warn('Some plugins failed to load', {
134
181
  successCount: results.length,
@@ -145,6 +192,12 @@ export class PluginLoader {
145
192
  });
146
193
  return results;
147
194
  }
195
+ /**
196
+ * Validates that a plugin implements the required interface
197
+ * @param plugin - Plugin to validate
198
+ * @param packageName - Package name for error reporting
199
+ * @throws {PluginRegistrationError} When plugin is invalid
200
+ */
148
201
  static validatePluginInterface(plugin, packageName) {
149
202
  if (!plugin || typeof plugin !== 'object') {
150
203
  throw new PluginRegistrationError(`Plugin from package '${packageName}' must be an object`, packageName);
@@ -159,6 +212,7 @@ export class PluginLoader {
159
212
  if (typeof p.validate !== 'function') {
160
213
  throw new PluginRegistrationError(`Plugin from package '${packageName}' must implement validate method`, packageName);
161
214
  }
215
+ // Validate optional fields if present
162
216
  if (p.description !== undefined && typeof p.description !== 'string') {
163
217
  throw new PluginRegistrationError(`Plugin from package '${packageName}' description must be a string`, packageName);
164
218
  }
@@ -169,23 +223,38 @@ export class PluginLoader {
169
223
  throw new PluginRegistrationError(`Plugin from package '${packageName}' metadata must be an object`, packageName);
170
224
  }
171
225
  }
226
+ /**
227
+ * Gets all loaded plugins
228
+ * @returns Array of loaded plugin results
229
+ */
172
230
  getLoadedPlugins() {
173
231
  return Array.from(this.loadedPlugins.values());
174
232
  }
233
+ /**
234
+ * Clears the plugin cache
235
+ */
175
236
  clearCache() {
176
237
  this.loadedPlugins.clear();
177
238
  this.logger.debug('Plugin cache cleared', {
178
239
  operation: 'cache_cleared',
179
240
  });
180
241
  }
242
+ /**
243
+ * Loads a module with timeout protection
244
+ * @param modulePath - Module path to load
245
+ * @returns Loaded plugin
246
+ * @private
247
+ */
181
248
  async loadModuleWithTimeout(modulePath) {
182
249
  return new Promise((resolve, reject) => {
183
250
  const timeout = globalThis.setTimeout(() => {
184
251
  reject(new Error(`Plugin loading timed out after ${this.options.loadTimeout}ms`));
185
252
  }, this.options.loadTimeout);
253
+ // Use dynamic import to load the module
186
254
  import(modulePath)
187
255
  .then((module) => {
188
256
  globalThis.clearTimeout(timeout);
257
+ // Handle different export patterns
189
258
  const plugin = module.default || module;
190
259
  if (!plugin) {
191
260
  reject(new Error('Plugin module does not export a plugin'));
@@ -199,11 +268,24 @@ export class PluginLoader {
199
268
  });
200
269
  });
201
270
  }
271
+ /**
272
+ * Validates plugin interface (instance method)
273
+ * @param plugin - Plugin to validate
274
+ * @param packageName - Package name for error reporting
275
+ * @private
276
+ */
202
277
  validatePluginInterface(plugin, packageName) {
203
278
  PluginLoader.validatePluginInterface(plugin, packageName);
204
279
  }
280
+ /**
281
+ * Checks plugin compatibility with current environment
282
+ * @param plugin - Plugin to check
283
+ * @returns Array of compatibility issues
284
+ * @private
285
+ */
205
286
  checkCompatibility(plugin) {
206
287
  const issues = [];
288
+ // Check Kubernetes version compatibility
207
289
  if (plugin.metadata?.kubernetesVersions) {
208
290
  const supportedVersions = new Set(this.options.supportedKubernetesVersions);
209
291
  const pluginVersions = plugin.metadata.kubernetesVersions;
@@ -212,9 +294,18 @@ export class PluginLoader {
212
294
  issues.push(`Plugin requires Kubernetes versions [${pluginVersions.join(', ')}] but only [${this.options.supportedKubernetesVersions.join(', ')}] are supported`);
213
295
  }
214
296
  }
297
+ // Add more compatibility checks as needed
215
298
  return issues;
216
299
  }
300
+ /**
301
+ * Determines if plugin should be loaded in current environment
302
+ * @param _plugin - Plugin to check (unused for now)
303
+ * @returns True if plugin should be loaded
304
+ * @private
305
+ */
217
306
  shouldLoadInEnvironment(_plugin) {
307
+ // For now, always return true
308
+ // This could be extended to check plugin metadata for environment restrictions
218
309
  return true;
219
310
  }
220
311
  }
@@ -1,14 +1,68 @@
1
+ /**
2
+ * Plugin Registry
3
+ *
4
+ * This module manages the lifecycle of policy plugins including registration,
5
+ * validation, and configuration management.
6
+ *
7
+ * @since 3.0.0
8
+ */
1
9
  import type { PolicyPlugin } from './types.js';
10
+ /**
11
+ * Registry for managing policy plugins
12
+ */
2
13
  export declare class PluginRegistry {
3
14
  private plugins;
4
15
  private pluginConfigs;
16
+ /**
17
+ * Registers a policy plugin with optional configuration
18
+ * @param plugin - The policy plugin to register
19
+ * @param config - Optional plugin-specific configuration
20
+ * @throws {PluginRegistrationError} When plugin validation fails
21
+ */
5
22
  register(plugin: PolicyPlugin, config?: unknown): void;
23
+ /**
24
+ * Gets a plugin by name
25
+ * @param name - Plugin name
26
+ * @returns Plugin instance or undefined if not found
27
+ */
6
28
  getPlugin(name: string): PolicyPlugin | undefined;
29
+ /**
30
+ * Gets all registered plugins
31
+ * @returns Array of all registered plugins
32
+ */
7
33
  getAllPlugins(): PolicyPlugin[];
34
+ /**
35
+ * Gets plugin configuration
36
+ * @param pluginName - Name of the plugin
37
+ * @returns Plugin configuration or undefined if not set
38
+ */
8
39
  getPluginConfig(pluginName: string): unknown;
40
+ /**
41
+ * Checks if a plugin is registered
42
+ * @param name - Plugin name
43
+ * @returns True if plugin is registered
44
+ */
9
45
  hasPlugin(name: string): boolean;
46
+ /**
47
+ * Gets the number of registered plugins
48
+ * @returns Number of registered plugins
49
+ */
10
50
  getPluginCount(): number;
51
+ /**
52
+ * Unregisters a plugin
53
+ * @param name - Plugin name to unregister
54
+ * @returns True if plugin was removed, false if not found
55
+ */
11
56
  unregister(name: string): boolean;
57
+ /**
58
+ * Clears all registered plugins
59
+ */
12
60
  clear(): void;
61
+ /**
62
+ * Validates that a plugin implements the required interface
63
+ * @param plugin - Plugin to validate
64
+ * @throws {PluginRegistrationError} When plugin is invalid
65
+ * @private
66
+ */
13
67
  private validatePlugin;
14
68
  }
@@ -1,11 +1,29 @@
1
+ /**
2
+ * Plugin Registry
3
+ *
4
+ * This module manages the lifecycle of policy plugins including registration,
5
+ * validation, and configuration management.
6
+ *
7
+ * @since 3.0.0
8
+ */
1
9
  import { PluginRegistrationError } from './errors.js';
10
+ /**
11
+ * Registry for managing policy plugins
12
+ */
2
13
  export class PluginRegistry {
3
14
  constructor() {
4
15
  this.plugins = new Map();
5
16
  this.pluginConfigs = new Map();
6
17
  }
18
+ /**
19
+ * Registers a policy plugin with optional configuration
20
+ * @param plugin - The policy plugin to register
21
+ * @param config - Optional plugin-specific configuration
22
+ * @throws {PluginRegistrationError} When plugin validation fails
23
+ */
7
24
  register(plugin, config) {
8
25
  this.validatePlugin(plugin);
26
+ // Check for duplicate plugin names
9
27
  if (this.plugins.has(plugin.name)) {
10
28
  throw new PluginRegistrationError(`Plugin with name '${plugin.name}' is already registered`, plugin.name);
11
29
  }
@@ -14,21 +32,49 @@ export class PluginRegistry {
14
32
  this.pluginConfigs.set(plugin.name, config);
15
33
  }
16
34
  }
35
+ /**
36
+ * Gets a plugin by name
37
+ * @param name - Plugin name
38
+ * @returns Plugin instance or undefined if not found
39
+ */
17
40
  getPlugin(name) {
18
41
  return this.plugins.get(name);
19
42
  }
43
+ /**
44
+ * Gets all registered plugins
45
+ * @returns Array of all registered plugins
46
+ */
20
47
  getAllPlugins() {
21
48
  return Array.from(this.plugins.values());
22
49
  }
50
+ /**
51
+ * Gets plugin configuration
52
+ * @param pluginName - Name of the plugin
53
+ * @returns Plugin configuration or undefined if not set
54
+ */
23
55
  getPluginConfig(pluginName) {
24
56
  return this.pluginConfigs.get(pluginName);
25
57
  }
58
+ /**
59
+ * Checks if a plugin is registered
60
+ * @param name - Plugin name
61
+ * @returns True if plugin is registered
62
+ */
26
63
  hasPlugin(name) {
27
64
  return this.plugins.has(name);
28
65
  }
66
+ /**
67
+ * Gets the number of registered plugins
68
+ * @returns Number of registered plugins
69
+ */
29
70
  getPluginCount() {
30
71
  return this.plugins.size;
31
72
  }
73
+ /**
74
+ * Unregisters a plugin
75
+ * @param name - Plugin name to unregister
76
+ * @returns True if plugin was removed, false if not found
77
+ */
32
78
  unregister(name) {
33
79
  const removed = this.plugins.delete(name);
34
80
  if (removed) {
@@ -36,10 +82,19 @@ export class PluginRegistry {
36
82
  }
37
83
  return removed;
38
84
  }
85
+ /**
86
+ * Clears all registered plugins
87
+ */
39
88
  clear() {
40
89
  this.plugins.clear();
41
90
  this.pluginConfigs.clear();
42
91
  }
92
+ /**
93
+ * Validates that a plugin implements the required interface
94
+ * @param plugin - Plugin to validate
95
+ * @throws {PluginRegistrationError} When plugin is invalid
96
+ * @private
97
+ */
43
98
  validatePlugin(plugin) {
44
99
  if (!plugin) {
45
100
  throw new PluginRegistrationError('Plugin cannot be null or undefined');
@@ -56,6 +111,7 @@ export class PluginRegistry {
56
111
  if (typeof plugin.validate !== 'function') {
57
112
  throw new PluginRegistrationError('Plugin must implement validate method', plugin.name);
58
113
  }
114
+ // Validate optional fields if present
59
115
  if (plugin.description !== undefined && typeof plugin.description !== 'string') {
60
116
  throw new PluginRegistrationError('Plugin description must be a string', plugin.name);
61
117
  }