import { Plugins, PluginInterfaces, PluginContext, Injector, Plugin, PluginKind, ClassPlugin, FactoryPlugin, InjectionToken, tokens, commonTokens, ValuePlugin, } from '@stryker-mutator/api/plugin'; import { InjectableFunction, InjectableClass } from 'typed-inject'; import { coreTokens } from './index.js'; export class PluginCreator { public static readonly inject = tokens( coreTokens.pluginsByKind, commonTokens.injector, ); constructor( private readonly pluginsByKind: Map>>, private readonly injector: Injector, ) {} public create( kind: TPlugin, name: string, ): PluginInterfaces[TPlugin] { const plugin = this.findPlugin(kind, name); if (isFactoryPlugin(plugin)) { return this.injector.injectFunction( plugin.factory as InjectableFunction< PluginContext, PluginInterfaces[TPlugin], Array> >, ); } else if (isClassPlugin(plugin)) { return this.injector.injectClass( plugin.injectableClass as InjectableClass< PluginContext, PluginInterfaces[TPlugin], Array> >, ); } else if (isValuePlugin(plugin)) { return plugin.value; } throw new Error( `Plugin "${kind}:${name}" could not be created, missing "factory", "injectableClass" or "value" property.`, ); } private findPlugin( kind: T, name: string, ): Plugins[T] { const plugins = this.pluginsByKind.get(kind); if (plugins) { const pluginFound = plugins.find( (plugin) => plugin.name.toLowerCase() === name.toLowerCase(), ); if (pluginFound) { return pluginFound as Plugins[T]; } else { throw new Error( `Cannot find ${kind} plugin "${name}". Did you forget to install it? Loaded ${kind} plugins were: ${new Intl.ListFormat('en').format(plugins.map((p) => `"${p.name}"`))}`, ); } } else { throw new Error( `Cannot find ${kind} plugin "${name}". In fact, no ${kind} plugins were loaded. Did you forget to install it?`, ); } } } function isFactoryPlugin( plugin: Plugin, ): plugin is FactoryPlugin>> { return Boolean( (plugin as FactoryPlugin>>) .factory, ); } function isClassPlugin( plugin: Plugin, ): plugin is ClassPlugin>> { return Boolean( (plugin as ClassPlugin>>) .injectableClass, ); } function isValuePlugin( plugin: Plugin, ): plugin is ValuePlugin { return Boolean((plugin as ValuePlugin).value); }