1 | import { StrykerOptions, PartialStrykerOptions, strykerCoreSchema } from '@stryker-mutator/api/core';
|
2 | import { BaseContext, commonTokens, Injector, tokens } from '@stryker-mutator/api/plugin';
|
3 | import { deepFreeze } from '@stryker-mutator/util';
|
4 | import { execaCommand } from 'execa';
|
5 |
|
6 | import { ConfigReader } from '../config/config-reader.js';
|
7 | import { LogConfigurator } from '../logging/index.js';
|
8 | import { coreTokens, PluginCreator } from '../di/index.js';
|
9 | import { TemporaryDirectory } from '../utils/temporary-directory.js';
|
10 | import { ConfigError } from '../errors.js';
|
11 | import { PluginLoader } from '../di/plugin-loader.js';
|
12 | import { reporterPluginsFileUrl } from '../reporters/index.js';
|
13 | import { Timer } from '../utils/timer.js';
|
14 | import { MetaSchemaBuilder, OptionsValidator } from '../config/index.js';
|
15 | import { BroadcastReporter } from '../reporters/broadcast-reporter.js';
|
16 | import { UnexpectedExitHandler } from '../unexpected-exit-handler.js';
|
17 |
|
18 | import { FileSystem, ProjectReader } from '../fs/index.js';
|
19 |
|
20 | import { MutantInstrumenterContext } from './index.js';
|
21 |
|
22 | export class PrepareExecutor {
|
23 | public static readonly inject = tokens(commonTokens.injector);
|
24 | constructor(private readonly injector: Injector<BaseContext>) {}
|
25 |
|
26 | public async execute(cliOptions: PartialStrykerOptions): Promise<Injector<MutantInstrumenterContext>> {
|
27 |
|
28 | const timer = new Timer();
|
29 |
|
30 |
|
31 | LogConfigurator.configureMainProcess(cliOptions.logLevel, cliOptions.fileLogLevel, cliOptions.allowConsoleColors);
|
32 |
|
33 |
|
34 | const configReaderInjector = this.injector
|
35 | .provideValue(coreTokens.validationSchema, strykerCoreSchema)
|
36 | .provideClass(coreTokens.optionsValidator, OptionsValidator);
|
37 | const configReader = configReaderInjector.injectClass(ConfigReader);
|
38 | const options: StrykerOptions = await configReader.readConfig(cliOptions);
|
39 |
|
40 |
|
41 | const pluginLoader = configReaderInjector.injectClass(PluginLoader);
|
42 | const pluginDescriptors = [...options.plugins, reporterPluginsFileUrl, ...options.appendPlugins];
|
43 | const loadedPlugins = await pluginLoader.load(pluginDescriptors);
|
44 |
|
45 |
|
46 | const metaSchemaBuilder = configReaderInjector.injectClass(MetaSchemaBuilder);
|
47 | const metaSchema = metaSchemaBuilder.buildMetaSchema(loadedPlugins.schemaContributions);
|
48 | const optionsValidatorInjector = configReaderInjector.provideValue(coreTokens.validationSchema, metaSchema);
|
49 | const validator: OptionsValidator = optionsValidatorInjector.injectClass(OptionsValidator);
|
50 | validator.validate(options, true);
|
51 |
|
52 |
|
53 | deepFreeze(options);
|
54 |
|
55 |
|
56 | const loggingContext = await LogConfigurator.configureLoggingServer(options.logLevel, options.fileLogLevel, options.allowConsoleColors);
|
57 |
|
58 |
|
59 | const projectFileReaderInjector = optionsValidatorInjector
|
60 | .provideValue(commonTokens.options, options)
|
61 | .provideClass(coreTokens.temporaryDirectory, TemporaryDirectory)
|
62 | .provideClass(coreTokens.fs, FileSystem)
|
63 | .provideValue(coreTokens.pluginsByKind, loadedPlugins.pluginsByKind);
|
64 | const project = await projectFileReaderInjector.injectClass(ProjectReader).read();
|
65 |
|
66 | if (project.isEmpty) {
|
67 | throw new ConfigError('No input files found.');
|
68 | } else {
|
69 |
|
70 | await projectFileReaderInjector.resolve(coreTokens.temporaryDirectory).initialize();
|
71 | return projectFileReaderInjector
|
72 | .provideValue(coreTokens.project, project)
|
73 | .provideValue(commonTokens.fileDescriptions, project.fileDescriptions)
|
74 | .provideClass(coreTokens.pluginCreator, PluginCreator)
|
75 | .provideClass(coreTokens.reporter, BroadcastReporter)
|
76 | .provideValue(coreTokens.timer, timer)
|
77 | .provideValue(coreTokens.project, project)
|
78 | .provideValue(coreTokens.loggingContext, loggingContext)
|
79 | .provideValue(coreTokens.execa, execaCommand)
|
80 | .provideValue(coreTokens.process, process)
|
81 | .provideClass(coreTokens.unexpectedExitRegistry, UnexpectedExitHandler)
|
82 | .provideValue(coreTokens.pluginModulePaths, loadedPlugins.pluginModulePaths);
|
83 | }
|
84 | }
|
85 | }
|