@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
103 lines (97 loc) • 2.96 kB
text/typescript
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<PluginKind, Array<Plugin<PluginKind>>>,
private readonly injector: Injector<PluginContext>,
) {}
public create<TPlugin extends keyof Plugins>(
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<InjectionToken<PluginContext>>
>,
);
} else if (isClassPlugin(plugin)) {
return this.injector.injectClass(
plugin.injectableClass as InjectableClass<
PluginContext,
PluginInterfaces[TPlugin],
Array<InjectionToken<PluginContext>>
>,
);
} 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<T extends keyof Plugins>(
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<PluginKind>,
): plugin is FactoryPlugin<PluginKind, Array<InjectionToken<PluginContext>>> {
return Boolean(
(plugin as FactoryPlugin<PluginKind, Array<InjectionToken<PluginContext>>>)
.factory,
);
}
function isClassPlugin(
plugin: Plugin<PluginKind>,
): plugin is ClassPlugin<PluginKind, Array<InjectionToken<PluginContext>>> {
return Boolean(
(plugin as ClassPlugin<PluginKind, Array<InjectionToken<PluginContext>>>)
.injectableClass,
);
}
function isValuePlugin(
plugin: Plugin<PluginKind>,
): plugin is ValuePlugin<PluginKind> {
return Boolean((plugin as ValuePlugin<PluginKind>).value);
}