tstyche 3.0.0-beta.5 → 3.0.0-rc.0

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.
@@ -65,7 +65,7 @@ declare class Diagnostic {
65
65
  static warning(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
66
66
  }
67
67
 
68
- type DiagnosticsHandler$1 = (this: void, diagnostic: Diagnostic) => void;
68
+ type DiagnosticsHandler<T extends Diagnostic | Array<Diagnostic> = Diagnostic> = (this: void, diagnostics: T) => void;
69
69
 
70
70
  declare enum TestMemberBrand {
71
71
  Describe = "describe",
@@ -130,22 +130,17 @@ declare enum OptionBrand {
130
130
  List = "list"
131
131
  }
132
132
 
133
- declare enum OptionGroup {
134
- CommandLine = 2,
135
- ConfigFile = 4
136
- }
137
-
138
133
  declare class ConfigDiagnosticText {
139
- #private;
140
134
  static expected(element: string): string;
141
135
  static expectsListItemType(optionName: string, optionBrand: OptionBrand): string;
142
- static expectsValue(optionName: string, optionGroup: OptionGroup): string;
136
+ static expectsValue(optionName: string): string;
143
137
  static fileDoesNotExist(filePath: string): string;
144
138
  static moduleWasNotFound(specifier: string): string;
145
139
  static seen(element: string): string;
146
140
  static testFileMatchCannotStartWith(segment: string): Array<string>;
147
- static requiresValueType(optionName: string, optionBrand: OptionBrand, optionGroup: OptionGroup): string;
141
+ static requiresValueType(optionName: string, optionBrand: OptionBrand): string;
148
142
  static unknownOption(optionName: string): string;
143
+ static usage(optionName: string, optionBrand: OptionBrand): Promise<Array<string>>;
149
144
  static versionIsNotSupported(value: string): string;
150
145
  static watchCannotBeEnabled(): string;
151
146
  }
@@ -283,12 +278,12 @@ declare class Config {
283
278
  static resolveConfigFilePath(filePath?: string): string;
284
279
  }
285
280
 
286
- interface ItemDefinition {
287
- brand: OptionBrand.String;
288
- name: string;
289
- pattern?: string;
281
+ declare enum OptionGroup {
282
+ CommandLine = 2,
283
+ ConfigFile = 4,
284
+ ResolvedConfig = 6
290
285
  }
291
- type OptionDefinition = PrimitiveTypeOptionDefinition | ListTypeOptionDefinition;
286
+
292
287
  interface BaseOptionDefinition {
293
288
  brand: OptionBrand;
294
289
  description: string;
@@ -298,13 +293,21 @@ interface BaseOptionDefinition {
298
293
  interface PrimitiveTypeOptionDefinition extends BaseOptionDefinition {
299
294
  brand: OptionBrand.String | OptionBrand.Number | OptionBrand.Boolean | OptionBrand.BareTrue;
300
295
  }
296
+ interface ItemDefinition {
297
+ brand: OptionBrand.String;
298
+ name: string;
299
+ pattern?: string;
300
+ }
301
301
  interface ListTypeOptionDefinition extends BaseOptionDefinition {
302
302
  brand: OptionBrand.List;
303
303
  items: ItemDefinition;
304
304
  }
305
+ type OptionDefinition = PrimitiveTypeOptionDefinition | ListTypeOptionDefinition;
305
306
  declare class Options {
306
307
  #private;
307
308
  static for(optionGroup: OptionGroup): Map<string, OptionDefinition>;
309
+ static resolve(optionName: string, optionValue: string, rootPath?: string): string;
310
+ static validate(optionName: string, optionValue: string, optionBrand: OptionBrand, onDiagnostics: DiagnosticsHandler, origin?: DiagnosticOrigin): Promise<void>;
308
311
  }
309
312
 
310
313
  declare const defaultOptions: Required<ConfigFileOptions>;
@@ -335,9 +338,9 @@ interface EnvironmentOptions {
335
338
  */
336
339
  timeout: number;
337
340
  /**
338
- * The path to the currently installed TypeScript module.
341
+ * The specifier of the TypeScript module.
339
342
  */
340
- typescriptPath: string | undefined;
343
+ typescriptModule: string | undefined;
341
344
  }
342
345
 
343
346
  declare const environmentOptions: EnvironmentOptions;
@@ -549,8 +552,6 @@ declare class EventEmitter {
549
552
  removeReporters(): void;
550
553
  }
551
554
 
552
- type ArgumentNode = ts.Expression | ts.TypeNode;
553
- type DiagnosticsHandler = (diagnostics: Diagnostic | Array<Diagnostic>) => void;
554
555
  interface MatchResult {
555
556
  explain: () => Array<Diagnostic>;
556
557
  isMatch: boolean;
@@ -565,136 +566,29 @@ interface TypeChecker extends ts.TypeChecker {
565
566
  };
566
567
  }
567
568
 
568
- declare class MatchWorker {
569
- #private;
570
- assertion: Assertion;
571
- constructor(compiler: typeof ts, typeChecker: TypeChecker, assertion: Assertion);
572
- checkIsAssignableTo(sourceNode: ArgumentNode, targetNode: ArgumentNode): boolean;
573
- checkIsAssignableWith(sourceNode: ArgumentNode, targetNode: ArgumentNode): boolean;
574
- checkIsIdenticalTo(sourceNode: ArgumentNode, targetNode: ArgumentNode): boolean;
575
- checkIsSubtype(sourceNode: ArgumentNode, targetNode: ArgumentNode): boolean;
576
- extendsObjectType(type: ts.Type): boolean;
577
- getParameterType(signature: ts.Signature, index: number): ts.Type | undefined;
578
- getSignatures(node: ArgumentNode): Array<ts.Signature>;
579
- getTypeText(node: ArgumentNode): string;
580
- getType(node: ArgumentNode): ts.Type;
581
- isAnyOrNeverType(type: ts.Type): type is ts.StringLiteralType | ts.NumberLiteralType;
582
- isStringOrNumberLiteralType(type: ts.Type): type is ts.StringLiteralType | ts.NumberLiteralType;
583
- isObjectType(type: ts.Type): type is ts.ObjectType;
584
- isUnionType(type: ts.Type): type is ts.UnionType;
585
- isUniqueSymbolType(type: ts.Type): type is ts.UniqueESSymbolType;
586
- resolveDiagnosticOrigin(symbol: ts.Symbol, enclosingNode: ts.Node): DiagnosticOrigin;
587
- }
588
-
589
- declare class PrimitiveTypeMatcher {
590
- #private;
591
- constructor(targetTypeFlag: ts.TypeFlags);
592
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode): MatchResult;
593
- }
594
-
595
- declare class ToAcceptProps {
596
- #private;
597
- constructor(compiler: typeof ts, typeChecker: TypeChecker);
598
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode, onDiagnostics: DiagnosticsHandler): MatchResult | undefined;
599
- }
600
-
601
- declare class ExpectDiagnosticText {
602
- static argumentOrTypeArgumentMustBeProvided(argumentNameText: string, typeArgumentNameText: string): string;
603
- static argumentMustBe(argumentNameText: string, expectedText: string): string;
604
- static argumentMustBeProvided(argumentNameText: string): string;
605
- static componentAcceptsProps(isTypeNode: boolean): string;
606
- static componentDoesNotAcceptProps(isTypeNode: boolean): string;
607
- static matcherIsDeprecated(matcherNameText: string): Array<string>;
608
- static matcherIsNotSupported(matcherNameText: string): string;
609
- static overloadGaveTheFollowingError(index: number, count: number, signatureText: string): string;
610
- static raisedTypeError(count?: number): string;
611
- static typeArgumentMustBe(argumentNameText: string, expectedText: string): string;
612
- static typeDidNotRaiseError(isTypeNode: boolean): string;
613
- static typeDidNotRaiseMatchingError(isTypeNode: boolean): string;
614
- static typeDoesNotHaveProperty(typeText: string, propertyNameText: string): string;
615
- static typeDoesMatch(sourceTypeText: string, targetTypeText: string): string;
616
- static typeDoesNotMatch(sourceTypeText: string, targetTypeText: string): string;
617
- static typeHasProperty(typeText: string, propertyNameText: string): string;
618
- static typeIs(typeText: string): string;
619
- static typeIsAssignableTo(sourceTypeText: string, targetTypeText: string): string;
620
- static typeIsAssignableWith(sourceTypeText: string, targetTypeText: string): string;
621
- static typeIsIdenticalTo(sourceTypeText: string, targetTypeText: string): string;
622
- static typeIsNotAssignableTo(sourceTypeText: string, targetTypeText: string): string;
623
- static typeIsNotAssignableWith(sourceTypeText: string, targetTypeText: string): string;
624
- static typeIsNotCompatibleWith(sourceTypeText: string, targetTypeText: string): string;
625
- static typeIsNotIdenticalTo(sourceTypeText: string, targetTypeText: string): string;
626
- static typeRaisedError(isTypeNode: boolean, count: number, targetCount: number): string;
627
- static typeRaisedMatchingError(isTypeNode: boolean): string;
628
- static typeRequiresProperty(typeText: string, propertyNameText: string): string;
629
- static typesOfPropertyAreNotCompatible(propertyNameText: string): string;
630
- }
631
-
632
- declare abstract class RelationMatcherBase {
633
- abstract explainText(sourceTypeText: string, targetTypeText: string): string;
634
- abstract explainNotText(sourceTypeText: string, targetTypeText: string): string;
635
- protected explain(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): Diagnostic[];
636
- abstract match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): MatchResult;
637
- }
638
-
639
- declare class ToBe extends RelationMatcherBase {
640
- explainText: typeof ExpectDiagnosticText.typeIsIdenticalTo;
641
- explainNotText: typeof ExpectDiagnosticText.typeIsNotIdenticalTo;
642
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): MatchResult;
643
- }
644
-
645
- declare class ToBeAssignableTo extends RelationMatcherBase {
646
- explainText: typeof ExpectDiagnosticText.typeIsAssignableTo;
647
- explainNotText: typeof ExpectDiagnosticText.typeIsNotAssignableTo;
648
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): MatchResult;
649
- }
650
-
651
- declare class ToBeAssignableWith extends RelationMatcherBase {
652
- explainText: typeof ExpectDiagnosticText.typeIsAssignableWith;
653
- explainNotText: typeof ExpectDiagnosticText.typeIsNotAssignableWith;
654
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): MatchResult;
655
- }
656
-
657
- declare class ToHaveProperty {
658
- #private;
659
- constructor(compiler: typeof ts);
660
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode, onDiagnostics: DiagnosticsHandler): MatchResult | undefined;
661
- }
662
-
663
- declare class ToMatch extends RelationMatcherBase {
664
- explainText: typeof ExpectDiagnosticText.typeDoesMatch;
665
- explainNotText: typeof ExpectDiagnosticText.typeDoesNotMatch;
666
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNode: ArgumentNode): MatchResult;
667
- }
668
-
669
- declare class ToRaiseError {
670
- #private;
671
- constructor(compiler: typeof ts);
672
- match(matchWorker: MatchWorker, sourceNode: ArgumentNode, targetNodes: Array<ArgumentNode>, onDiagnostics: DiagnosticsHandler): MatchResult | undefined;
673
- }
674
-
675
569
  declare class ExpectService {
676
570
  #private;
677
- toAcceptProps: ToAcceptProps;
678
- toBe: ToBe;
679
- toBeAny: PrimitiveTypeMatcher;
680
- toBeAssignableTo: ToBeAssignableTo;
681
- toBeAssignableWith: ToBeAssignableWith;
682
- toBeBigInt: PrimitiveTypeMatcher;
683
- toBeBoolean: PrimitiveTypeMatcher;
684
- toBeNever: PrimitiveTypeMatcher;
685
- toBeNull: PrimitiveTypeMatcher;
686
- toBeNumber: PrimitiveTypeMatcher;
687
- toBeString: PrimitiveTypeMatcher;
688
- toBeSymbol: PrimitiveTypeMatcher;
689
- toBeUndefined: PrimitiveTypeMatcher;
690
- toBeUniqueSymbol: PrimitiveTypeMatcher;
691
- toBeUnknown: PrimitiveTypeMatcher;
692
- toBeVoid: PrimitiveTypeMatcher;
693
- toHaveProperty: ToHaveProperty;
694
- toMatch: ToMatch;
695
- toRaiseError: ToRaiseError;
571
+ private toAcceptProps;
572
+ private toBe;
573
+ private toBeAny;
574
+ private toBeAssignableTo;
575
+ private toBeAssignableWith;
576
+ private toBeBigInt;
577
+ private toBeBoolean;
578
+ private toBeNever;
579
+ private toBeNull;
580
+ private toBeNumber;
581
+ private toBeString;
582
+ private toBeSymbol;
583
+ private toBeUndefined;
584
+ private toBeUniqueSymbol;
585
+ private toBeUnknown;
586
+ private toBeVoid;
587
+ private toHaveProperty;
588
+ private toMatch;
589
+ private toRaiseError;
696
590
  constructor(compiler: typeof ts, typeChecker: TypeChecker);
697
- match(assertion: Assertion, onDiagnostics: DiagnosticsHandler): MatchResult | undefined;
591
+ match(assertion: Assertion, onDiagnostics: DiagnosticsHandler<Diagnostic | Array<Diagnostic>>): MatchResult | undefined;
698
592
  }
699
593
 
700
594
  declare class CancellationHandler implements EventHandler {
@@ -714,25 +608,6 @@ declare class ResultHandler implements EventHandler {
714
608
  on([event, payload]: Event): void;
715
609
  }
716
610
 
717
- interface Hooks {
718
- /**
719
- * Is called after configuration is resolved and allows to modify it.
720
- */
721
- config?: (resolvedConfig: ResolvedConfig) => ResolvedConfig | Promise<ResolvedConfig>;
722
- /**
723
- * Is called after test files are selected and allows to modify the list.
724
- */
725
- select?: (testFiles: Array<string>) => Array<string | URL> | Promise<Array<string | URL>>;
726
- }
727
-
728
- declare class HooksService {
729
- #private;
730
- static addHandler(hooks: Hooks): void;
731
- static call(hook: "config", resolvedConfig: ResolvedConfig): Promise<ResolvedConfig>;
732
- static call(hook: "select", testFiles: Array<string>): Promise<Array<string | URL>>;
733
- static removeHandlers(): void;
734
- }
735
-
736
611
  type InputHandler = (chunk: string) => void;
737
612
  declare class InputService {
738
613
  #private;
@@ -849,6 +724,32 @@ declare class Path {
849
724
  static resolve(...filePaths: Array<string>): string;
850
725
  }
851
726
 
727
+ interface SelectHookContext {
728
+ resolvedConfig: ResolvedConfig;
729
+ }
730
+ interface Plugin {
731
+ /**
732
+ * The name of this plugin.
733
+ */
734
+ name: string;
735
+ /**
736
+ * Is called after configuration is resolved and allows to modify it.
737
+ */
738
+ config?: (resolvedConfig: ResolvedConfig) => ResolvedConfig | Promise<ResolvedConfig>;
739
+ /**
740
+ * Is called after test files are selected and allows to modify the list.
741
+ */
742
+ select?: (this: SelectHookContext, testFiles: Array<string>) => Array<string | URL> | Promise<Array<string | URL>>;
743
+ }
744
+
745
+ type Hooks = Required<Omit<Plugin, "name">>;
746
+ declare class PluginService {
747
+ #private;
748
+ static addHandler(plugin: Plugin): void;
749
+ static call<T extends keyof Hooks>(hook: T, argument: Parameters<Hooks[T]>[0], context: ThisParameterType<Hooks[T]>): Promise<Awaited<ReturnType<Hooks[T]>>>;
750
+ static removeHandlers(): void;
751
+ }
752
+
852
753
  declare class ProjectService {
853
754
  #private;
854
755
  constructor(resolvedConfig: ResolvedConfig, compiler: typeof ts);
@@ -917,4 +818,4 @@ declare class WatchService {
917
818
  watch(cancellationToken: CancellationToken): AsyncIterable<Array<Task>>;
918
819
  }
919
820
 
920
- export { Assertion, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, type CommandLineOptions, Config, ConfigDiagnosticText, type ConfigFileOptions, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, type DiagnosticsHandler$1 as DiagnosticsHandler, type EnvironmentOptions, type Event, EventEmitter, type EventHandler, ExitCodeHandler, ExpectResult, ExpectService, type FileWatchHandler, FileWatcher, type Hooks, HooksService, type InputHandler, InputService, type ItemDefinition, Line, ListReporter, type MatchResult, OptionBrand, type OptionDefinition, OptionGroup, Options, OutputService, Path, ProjectResult, ProjectService, type Reporter, type ReporterEvent, type ResolvedConfig, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, ScribblerJsx, type ScribblerOptions, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, type TargetResultStatus, Task, TaskResult, type TaskResultStatus, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, type TypeChecker, Version, type WatchHandler, WatchReporter, WatchService, Watcher, type WatcherOptions, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
821
+ export { Assertion, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, type CommandLineOptions, Config, ConfigDiagnosticText, type ConfigFileOptions, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, type DiagnosticsHandler, type EnvironmentOptions, type Event, EventEmitter, type EventHandler, ExitCodeHandler, ExpectResult, ExpectService, type FileWatchHandler, FileWatcher, type InputHandler, InputService, type ItemDefinition, Line, ListReporter, type MatchResult, OptionBrand, type OptionDefinition, OptionGroup, Options, OutputService, Path, type Plugin, PluginService, ProjectResult, ProjectService, type Reporter, type ReporterEvent, type ResolvedConfig, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, ScribblerJsx, type ScribblerOptions, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, type TargetResultStatus, Task, TaskResult, type TaskResultStatus, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, type TypeChecker, Version, type WatchHandler, WatchReporter, WatchService, Watcher, type WatcherOptions, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
package/build/tstyche.js CHANGED
@@ -1,65 +1,13 @@
1
- import { writeFileSync, rmSync, existsSync, watch } from 'node:fs';
2
1
  import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { pathToFileURL, fileURLToPath } from 'node:url';
5
2
  import { createRequire } from 'node:module';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
4
  import vm from 'node:vm';
7
5
  import os from 'node:os';
8
6
  import process from 'node:process';
7
+ import path from 'node:path';
8
+ import { writeFileSync, rmSync, existsSync, watch } from 'node:fs';
9
9
  import streamConsumers from 'node:stream/consumers';
10
10
 
11
- class ConfigDiagnosticText {
12
- static expected(element) {
13
- return `Expected ${element}.`;
14
- }
15
- static expectsListItemType(optionName, optionBrand) {
16
- return `Item of the '${optionName}' list must be of type ${optionBrand}.`;
17
- }
18
- static expectsValue(optionName, optionGroup) {
19
- optionName = ConfigDiagnosticText.#optionName(optionName, optionGroup);
20
- return `Option '${optionName}' expects a value.`;
21
- }
22
- static fileDoesNotExist(filePath) {
23
- return `The specified path '${filePath}' does not exist.`;
24
- }
25
- static moduleWasNotFound(specifier) {
26
- return `The specified module '${specifier}' was not found.`;
27
- }
28
- static #optionName(optionName, optionGroup) {
29
- switch (optionGroup) {
30
- case 2:
31
- return `--${optionName}`;
32
- case 4:
33
- return optionName;
34
- }
35
- }
36
- static seen(element) {
37
- return `The ${element} was seen here.`;
38
- }
39
- static testFileMatchCannotStartWith(segment) {
40
- return [
41
- `A test file match pattern cannot start with '${segment}'.`,
42
- "The test files are only collected within the 'rootPath' directory.",
43
- ];
44
- }
45
- static requiresValueType(optionName, optionBrand, optionGroup) {
46
- optionName = ConfigDiagnosticText.#optionName(optionName, optionGroup);
47
- return `Option '${optionName}' requires a value of type ${optionBrand}.`;
48
- }
49
- static unknownOption(optionName) {
50
- return `Unknown option '${optionName}'.`;
51
- }
52
- static versionIsNotSupported(value) {
53
- if (value === "current") {
54
- return "Cannot use 'current' as a target. Failed to resolve the path to the currently installed TypeScript module.";
55
- }
56
- return `TypeScript version '${value}' is not supported.`;
57
- }
58
- static watchCannotBeEnabled() {
59
- return "Watch mode cannot be enabled in continuous integration environment.";
60
- }
61
- }
62
-
63
11
  class DiagnosticOrigin {
64
12
  assertion;
65
13
  end;
@@ -169,49 +117,6 @@ class SourceFile {
169
117
  }
170
118
  }
171
119
 
172
- class EventEmitter {
173
- static instanceCount = 0;
174
- static #handlers = new Map();
175
- static #reporters = new Map();
176
- #scope;
177
- constructor() {
178
- this.#scope = EventEmitter.instanceCount++;
179
- EventEmitter.#handlers.set(this.#scope, new Set());
180
- EventEmitter.#reporters.set(this.#scope, new Set());
181
- }
182
- addHandler(handler) {
183
- EventEmitter.#handlers.get(this.#scope)?.add(handler);
184
- }
185
- addReporter(reporter) {
186
- EventEmitter.#reporters.get(this.#scope)?.add(reporter);
187
- }
188
- static dispatch(event) {
189
- function forEachHandler(handlers, event) {
190
- for (const handler of handlers) {
191
- handler.on(event);
192
- }
193
- }
194
- for (const handlers of EventEmitter.#handlers.values()) {
195
- forEachHandler(handlers, event);
196
- }
197
- for (const handlers of EventEmitter.#reporters.values()) {
198
- forEachHandler(handlers, event);
199
- }
200
- }
201
- removeHandler(handler) {
202
- EventEmitter.#handlers.get(this.#scope)?.delete(handler);
203
- }
204
- removeReporter(reporter) {
205
- EventEmitter.#reporters.get(this.#scope)?.delete(reporter);
206
- }
207
- removeHandlers() {
208
- EventEmitter.#handlers.get(this.#scope)?.clear();
209
- }
210
- removeReporters() {
211
- EventEmitter.#reporters.get(this.#scope)?.clear();
212
- }
213
- }
214
-
215
120
  class Path {
216
121
  static normalizeSlashes;
217
122
  static {
@@ -249,7 +154,7 @@ class Environment {
249
154
  npmRegistry: Environment.#resolveNpmRegistry(),
250
155
  storePath: Environment.#resolveStorePath(),
251
156
  timeout: Environment.#resolveTimeout(),
252
- typescriptPath: Environment.#resolveTypeScriptPath(),
157
+ typescriptModule: Environment.#resolveTypeScriptModule(),
253
158
  };
254
159
  }
255
160
  static #resolveIsCi() {
@@ -300,23 +205,66 @@ class Environment {
300
205
  }
301
206
  return 30;
302
207
  }
303
- static #resolveTypeScriptPath() {
208
+ static #resolveTypeScriptModule() {
304
209
  let specifier = "typescript";
305
- if (process.env["TSTYCHE_TYPESCRIPT_PATH"] != null) {
306
- specifier = process.env["TSTYCHE_TYPESCRIPT_PATH"];
210
+ if (process.env["TSTYCHE_TYPESCRIPT_MODULE"] != null) {
211
+ specifier = process.env["TSTYCHE_TYPESCRIPT_MODULE"];
307
212
  }
308
- let resolvedPath;
213
+ let resolvedModule;
309
214
  try {
310
- resolvedPath = Path.normalizeSlashes(createRequire(import.meta.url).resolve(specifier));
215
+ resolvedModule = import.meta.resolve(specifier);
311
216
  }
312
217
  catch {
313
218
  }
314
- return resolvedPath;
219
+ return resolvedModule;
315
220
  }
316
221
  }
317
222
 
318
223
  const environmentOptions = Environment.resolve();
319
224
 
225
+ class EventEmitter {
226
+ static instanceCount = 0;
227
+ static #handlers = new Map();
228
+ static #reporters = new Map();
229
+ #scope;
230
+ constructor() {
231
+ this.#scope = EventEmitter.instanceCount++;
232
+ EventEmitter.#handlers.set(this.#scope, new Set());
233
+ EventEmitter.#reporters.set(this.#scope, new Set());
234
+ }
235
+ addHandler(handler) {
236
+ EventEmitter.#handlers.get(this.#scope)?.add(handler);
237
+ }
238
+ addReporter(reporter) {
239
+ EventEmitter.#reporters.get(this.#scope)?.add(reporter);
240
+ }
241
+ static dispatch(event) {
242
+ function forEachHandler(handlers, event) {
243
+ for (const handler of handlers) {
244
+ handler.on(event);
245
+ }
246
+ }
247
+ for (const handlers of EventEmitter.#handlers.values()) {
248
+ forEachHandler(handlers, event);
249
+ }
250
+ for (const handlers of EventEmitter.#reporters.values()) {
251
+ forEachHandler(handlers, event);
252
+ }
253
+ }
254
+ removeHandler(handler) {
255
+ EventEmitter.#handlers.get(this.#scope)?.delete(handler);
256
+ }
257
+ removeReporter(reporter) {
258
+ EventEmitter.#reporters.get(this.#scope)?.delete(reporter);
259
+ }
260
+ removeHandlers() {
261
+ EventEmitter.#handlers.get(this.#scope)?.clear();
262
+ }
263
+ removeReporters() {
264
+ EventEmitter.#reporters.get(this.#scope)?.clear();
265
+ }
266
+ }
267
+
320
268
  class Version {
321
269
  static isGreaterThan(source, target) {
322
270
  return !(source === target) && Version.#satisfies(source, target);
@@ -724,8 +672,8 @@ class Store {
724
672
  return compilerInstance;
725
673
  }
726
674
  let modulePath;
727
- if (tag === "current" && environmentOptions.typescriptPath != null) {
728
- modulePath = environmentOptions.typescriptPath;
675
+ if (tag === "current" && environmentOptions.typescriptModule != null) {
676
+ modulePath = fileURLToPath(environmentOptions.typescriptModule);
729
677
  }
730
678
  else {
731
679
  await Store.open();
@@ -793,7 +741,7 @@ class Store {
793
741
  }
794
742
  static async validateTag(tag) {
795
743
  if (tag === "current") {
796
- return environmentOptions.typescriptPath != null;
744
+ return environmentOptions.typescriptModule != null;
797
745
  }
798
746
  await Store.open();
799
747
  if (Store.#manifest?.isOutdated({ ageTolerance: 60 }) &&
@@ -809,90 +757,64 @@ class Store {
809
757
  }
810
758
  }
811
759
 
812
- class OptionUsageText {
813
- #optionGroup;
814
- constructor(optionGroup) {
815
- this.#optionGroup = optionGroup;
816
- }
817
- async get(optionName, optionBrand) {
818
- const usageText = [];
819
- switch (optionName) {
760
+ class ConfigDiagnosticText {
761
+ static expected(element) {
762
+ return `Expected ${element}.`;
763
+ }
764
+ static expectsListItemType(optionName, optionBrand) {
765
+ return `Item of the '${optionName}' list must be of type ${optionBrand}.`;
766
+ }
767
+ static expectsValue(optionName) {
768
+ return `Option '${optionName}' expects a value.`;
769
+ }
770
+ static fileDoesNotExist(filePath) {
771
+ return `The specified path '${filePath}' does not exist.`;
772
+ }
773
+ static moduleWasNotFound(specifier) {
774
+ return `The specified module '${specifier}' was not found.`;
775
+ }
776
+ static seen(element) {
777
+ return `The ${element} was seen here.`;
778
+ }
779
+ static testFileMatchCannotStartWith(segment) {
780
+ return [
781
+ `A test file match pattern cannot start with '${segment}'.`,
782
+ "The test files are only collected within the 'rootPath' directory.",
783
+ ];
784
+ }
785
+ static requiresValueType(optionName, optionBrand) {
786
+ return `Option '${optionName}' requires a value of type ${optionBrand}.`;
787
+ }
788
+ static unknownOption(optionName) {
789
+ return `Unknown option '${optionName}'.`;
790
+ }
791
+ static async usage(optionName, optionBrand) {
792
+ switch (optionName.startsWith("--") ? optionName.slice(2) : optionName) {
820
793
  case "target": {
821
- switch (this.#optionGroup) {
822
- case 2:
823
- usageText.push("Value for the '--target' option must be a single tag or a comma separated list.", "Usage examples: '--target 4.9', '--target latest', '--target 4.9,5.3.2,current'.");
824
- break;
825
- case 4:
826
- usageText.push("Item of the 'target' list must be a supported version tag.");
827
- break;
794
+ const text = [];
795
+ if (optionName.startsWith("--")) {
796
+ text.push("Value for the '--target' option must be a single tag or a comma separated list.", "Usage examples: '--target 4.9', '--target latest', '--target 4.9,5.3.2,current'.");
797
+ }
798
+ else {
799
+ text.push("Item of the 'target' list must be a supported version tag.");
828
800
  }
829
801
  const supportedTags = await Store.getSupportedTags();
830
802
  if (supportedTags != null) {
831
- usageText.push(`Supported tags: ${["'", supportedTags.join("', '"), "'"].join("")}.`);
803
+ text.push(`Supported tags: ${["'", supportedTags.join("', '"), "'"].join("")}.`);
832
804
  }
833
- break;
805
+ return text;
834
806
  }
835
- default:
836
- usageText.push(ConfigDiagnosticText.requiresValueType(optionName, optionBrand, this.#optionGroup));
837
807
  }
838
- return usageText;
839
- }
840
- }
841
-
842
- class OptionValidator {
843
- #onDiagnostics;
844
- #optionGroup;
845
- #optionUsageText;
846
- constructor(optionGroup, onDiagnostics) {
847
- this.#optionGroup = optionGroup;
848
- this.#onDiagnostics = onDiagnostics;
849
- this.#optionUsageText = new OptionUsageText(this.#optionGroup);
808
+ return [ConfigDiagnosticText.requiresValueType(optionName, optionBrand)];
850
809
  }
851
- async check(optionName, optionValue, optionBrand, origin) {
852
- switch (optionName) {
853
- case "tsconfig":
854
- if (["findup", "ignore"].includes(optionValue)) {
855
- break;
856
- }
857
- case "config":
858
- case "rootPath":
859
- if (!existsSync(optionValue)) {
860
- this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.fileDoesNotExist(optionValue), origin));
861
- }
862
- break;
863
- case "reporters":
864
- if (["list", "summary"].includes(optionValue)) {
865
- break;
866
- }
867
- case "plugins":
868
- try {
869
- await import(optionValue);
870
- }
871
- catch {
872
- this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.moduleWasNotFound(optionValue), origin));
873
- }
874
- break;
875
- case "target":
876
- if ((await Store.validateTag(optionValue)) === false) {
877
- this.#onDiagnostics(Diagnostic.error([
878
- ConfigDiagnosticText.versionIsNotSupported(optionValue),
879
- ...(await this.#optionUsageText.get(optionName, optionBrand)),
880
- ], origin));
881
- }
882
- break;
883
- case "testFileMatch":
884
- for (const segment of ["/", "../"]) {
885
- if (optionValue.startsWith(segment)) {
886
- this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.testFileMatchCannotStartWith(segment), origin));
887
- }
888
- }
889
- break;
890
- case "watch":
891
- if (environmentOptions.isCi) {
892
- this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.watchCannotBeEnabled(), origin));
893
- }
894
- break;
810
+ static versionIsNotSupported(value) {
811
+ if (value === "current") {
812
+ return "Cannot use 'current' as a target. Failed to resolve the installed TypeScript module.";
895
813
  }
814
+ return `TypeScript version '${value}' is not supported.`;
815
+ }
816
+ static watchCannotBeEnabled() {
817
+ return "Watch mode cannot be enabled in continuous integration environment.";
896
818
  }
897
819
  }
898
820
 
@@ -1039,29 +961,98 @@ class Options {
1039
961
  }
1040
962
  return definitionMap;
1041
963
  }
964
+ static resolve(optionName, optionValue, rootPath = ".") {
965
+ switch (optionName.startsWith("--") ? optionName.slice(2) : optionName) {
966
+ case "config":
967
+ case "rootPath":
968
+ case "tsconfig":
969
+ if (optionName.endsWith("tsconfig") && ["findup", "ignore"].includes(optionValue)) {
970
+ break;
971
+ }
972
+ optionValue = Path.resolve(rootPath, optionValue);
973
+ break;
974
+ case "plugins":
975
+ case "reporters":
976
+ if (optionName.endsWith("reporters") && ["list", "summary"].includes(optionValue)) {
977
+ break;
978
+ }
979
+ try {
980
+ if (optionValue.startsWith(".")) {
981
+ optionValue = pathToFileURL(Path.relative(".", Path.resolve(rootPath, optionValue))).toString();
982
+ }
983
+ else {
984
+ optionValue = import.meta.resolve(optionValue);
985
+ }
986
+ }
987
+ catch {
988
+ }
989
+ break;
990
+ }
991
+ return optionValue;
992
+ }
993
+ static async validate(optionName, optionValue, optionBrand, onDiagnostics, origin) {
994
+ switch (optionName.startsWith("--") ? optionName.slice(2) : optionName) {
995
+ case "config":
996
+ case "rootPath":
997
+ case "tsconfig":
998
+ if (optionName.endsWith("tsconfig") && ["findup", "ignore"].includes(optionValue)) {
999
+ break;
1000
+ }
1001
+ if (existsSync(optionValue)) {
1002
+ break;
1003
+ }
1004
+ onDiagnostics(Diagnostic.error(ConfigDiagnosticText.fileDoesNotExist(optionValue), origin));
1005
+ break;
1006
+ case "plugins":
1007
+ case "reporters":
1008
+ if (optionName.endsWith("reporters") && ["list", "summary"].includes(optionValue)) {
1009
+ break;
1010
+ }
1011
+ if (optionValue.startsWith("file:") && existsSync(new URL(optionValue))) {
1012
+ break;
1013
+ }
1014
+ onDiagnostics(Diagnostic.error(ConfigDiagnosticText.moduleWasNotFound(optionValue), origin));
1015
+ break;
1016
+ case "target":
1017
+ if ((await Store.validateTag(optionValue)) === false) {
1018
+ onDiagnostics(Diagnostic.error([
1019
+ ConfigDiagnosticText.versionIsNotSupported(optionValue),
1020
+ await ConfigDiagnosticText.usage(optionName, optionBrand),
1021
+ ].flat(), origin));
1022
+ }
1023
+ break;
1024
+ case "testFileMatch":
1025
+ for (const segment of ["/", "../"]) {
1026
+ if (optionValue.startsWith(segment)) {
1027
+ onDiagnostics(Diagnostic.error(ConfigDiagnosticText.testFileMatchCannotStartWith(segment), origin));
1028
+ }
1029
+ }
1030
+ break;
1031
+ case "watch":
1032
+ if (environmentOptions.isCi) {
1033
+ onDiagnostics(Diagnostic.error(ConfigDiagnosticText.watchCannotBeEnabled(), origin));
1034
+ }
1035
+ break;
1036
+ }
1037
+ }
1042
1038
  }
1043
1039
 
1044
1040
  class CommandLineParser {
1045
1041
  #commandLineOptions;
1046
1042
  #onDiagnostics;
1047
1043
  #options;
1048
- #optionGroup = 2;
1049
- #optionUsageText;
1050
- #optionValidator;
1051
1044
  #pathMatch;
1052
1045
  constructor(commandLine, pathMatch, onDiagnostics) {
1053
1046
  this.#commandLineOptions = commandLine;
1054
1047
  this.#pathMatch = pathMatch;
1055
1048
  this.#onDiagnostics = onDiagnostics;
1056
- this.#options = Options.for(this.#optionGroup);
1057
- this.#optionUsageText = new OptionUsageText(this.#optionGroup);
1058
- this.#optionValidator = new OptionValidator(this.#optionGroup, this.#onDiagnostics);
1049
+ this.#options = Options.for(2);
1059
1050
  }
1060
- async #onExpectsValue(optionDefinition) {
1051
+ async #onExpectsValue(optionName, optionBrand) {
1061
1052
  const text = [
1062
- ConfigDiagnosticText.expectsValue(optionDefinition.name, this.#optionGroup),
1063
- ...(await this.#optionUsageText.get(optionDefinition.name, optionDefinition.brand)),
1064
- ];
1053
+ ConfigDiagnosticText.expectsValue(optionName),
1054
+ await ConfigDiagnosticText.usage(optionName, optionBrand),
1055
+ ].flat();
1065
1056
  this.#onDiagnostics(Diagnostic.error(text));
1066
1057
  }
1067
1058
  async parse(commandLineArgs) {
@@ -1070,10 +1061,9 @@ class CommandLineParser {
1070
1061
  while (arg != null) {
1071
1062
  index++;
1072
1063
  if (arg.startsWith("--")) {
1073
- const optionName = arg.slice(2);
1074
- const optionDefinition = this.#options.get(optionName);
1064
+ const optionDefinition = this.#options.get(arg.slice(2));
1075
1065
  if (optionDefinition) {
1076
- index = await this.#parseOptionValue(commandLineArgs, index, optionDefinition);
1066
+ index = await this.#parseOptionValue(commandLineArgs, index, arg, optionDefinition);
1077
1067
  }
1078
1068
  else {
1079
1069
  this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.unknownOption(arg)));
@@ -1088,15 +1078,15 @@ class CommandLineParser {
1088
1078
  arg = commandLineArgs[index];
1089
1079
  }
1090
1080
  }
1091
- async #parseOptionValue(commandLineArgs, index, optionDefinition) {
1081
+ async #parseOptionValue(commandLineArgs, index, optionName, optionDefinition) {
1092
1082
  let optionValue = this.#resolveOptionValue(commandLineArgs[index]);
1093
1083
  switch (optionDefinition.brand) {
1094
1084
  case "bareTrue":
1095
- await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
1085
+ await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1096
1086
  this.#commandLineOptions[optionDefinition.name] = true;
1097
1087
  break;
1098
1088
  case "boolean":
1099
- await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
1089
+ await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1100
1090
  this.#commandLineOptions[optionDefinition.name] = optionValue !== "false";
1101
1091
  if (optionValue === "false" || optionValue === "true") {
1102
1092
  index++;
@@ -1104,39 +1094,29 @@ class CommandLineParser {
1104
1094
  break;
1105
1095
  case "list":
1106
1096
  if (optionValue !== "") {
1107
- let optionValues = optionValue
1097
+ const optionValues = optionValue
1108
1098
  .split(",")
1109
1099
  .map((value) => value.trim())
1110
- .filter((value) => value !== "");
1111
- if (optionDefinition.name === "plugins" || optionDefinition.name === "reporters") {
1112
- optionValues = optionValues.map((optionValue) => {
1113
- if (optionValue.startsWith(".")) {
1114
- return pathToFileURL(optionValue).toString();
1115
- }
1116
- return optionValue;
1117
- });
1118
- }
1100
+ .filter((value) => value !== "")
1101
+ .map((value) => Options.resolve(optionName, value));
1119
1102
  for (const optionValue of optionValues) {
1120
- await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
1103
+ await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1121
1104
  }
1122
1105
  this.#commandLineOptions[optionDefinition.name] = optionValues;
1123
1106
  index++;
1124
1107
  break;
1125
1108
  }
1126
- await this.#onExpectsValue(optionDefinition);
1109
+ await this.#onExpectsValue(optionName, optionDefinition.brand);
1127
1110
  break;
1128
1111
  case "string":
1129
1112
  if (optionValue !== "") {
1130
- if (optionDefinition.name === "config" ||
1131
- (optionDefinition.name === "tsconfig" && !["findup", "ignore"].includes(optionValue))) {
1132
- optionValue = Path.resolve(optionValue);
1133
- }
1134
- await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
1113
+ optionValue = Options.resolve(optionName, optionValue);
1114
+ await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1135
1115
  this.#commandLineOptions[optionDefinition.name] = optionValue;
1136
1116
  index++;
1137
1117
  break;
1138
1118
  }
1139
- await this.#onExpectsValue(optionDefinition);
1119
+ await this.#onExpectsValue(optionName, optionDefinition.brand);
1140
1120
  break;
1141
1121
  }
1142
1122
  return index;
@@ -1279,21 +1259,18 @@ class ConfigFileParser {
1279
1259
  #jsonScanner;
1280
1260
  #onDiagnostics;
1281
1261
  #options;
1282
- #optionGroup = 4;
1283
- #optionValidator;
1284
1262
  #sourceFile;
1285
1263
  constructor(configFileOptions, sourceFile, onDiagnostics) {
1286
1264
  this.#configFileOptions = configFileOptions;
1287
1265
  this.#sourceFile = sourceFile;
1288
1266
  this.#onDiagnostics = onDiagnostics;
1289
- this.#options = Options.for(this.#optionGroup);
1267
+ this.#options = Options.for(4);
1290
1268
  this.#jsonScanner = new JsonScanner(this.#sourceFile);
1291
- this.#optionValidator = new OptionValidator(this.#optionGroup, this.#onDiagnostics);
1292
1269
  }
1293
1270
  #onRequiresValue(optionDefinition, jsonNode, isListItem) {
1294
1271
  const text = isListItem
1295
1272
  ? ConfigDiagnosticText.expectsListItemType(optionDefinition.name, optionDefinition.brand)
1296
- : ConfigDiagnosticText.requiresValueType(optionDefinition.name, optionDefinition.brand, this.#optionGroup);
1273
+ : ConfigDiagnosticText.requiresValueType(optionDefinition.name, optionDefinition.brand);
1297
1274
  this.#onDiagnostics(Diagnostic.error(text, jsonNode.origin));
1298
1275
  }
1299
1276
  async #parseValue(optionDefinition, isListItem = false) {
@@ -1316,17 +1293,9 @@ class ConfigFileParser {
1316
1293
  this.#onRequiresValue(optionDefinition, jsonNode, isListItem);
1317
1294
  break;
1318
1295
  }
1319
- if (optionDefinition.name === "plugins" || optionDefinition.name === "reporters") {
1320
- if (optionValue.startsWith(".")) {
1321
- const configFilePath = Path.relative(".", Path.dirname(this.#sourceFile.fileName));
1322
- optionValue = pathToFileURL(Path.join(configFilePath, optionValue)).toString();
1323
- }
1324
- }
1325
- if (optionDefinition.name === "rootPath" ||
1326
- (optionDefinition.name === "tsconfig" && !["findup", "ignore"].includes(optionValue))) {
1327
- optionValue = Path.resolve(Path.dirname(this.#sourceFile.fileName), optionValue);
1328
- }
1329
- await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand, jsonNode.origin);
1296
+ const rootPath = Path.dirname(this.#sourceFile.fileName);
1297
+ optionValue = Options.resolve(optionDefinition.name, optionValue, rootPath);
1298
+ await Options.validate(optionDefinition.name, optionValue, optionDefinition.brand, this.#onDiagnostics, jsonNode.origin);
1330
1299
  break;
1331
1300
  }
1332
1301
  case "list": {
@@ -1430,14 +1399,14 @@ const defaultOptions = {
1430
1399
  plugins: [],
1431
1400
  reporters: ["list", "summary"],
1432
1401
  rootPath: Path.resolve("./"),
1433
- target: environmentOptions.typescriptPath != null ? ["current"] : ["latest"],
1402
+ target: environmentOptions.typescriptModule != null ? ["current"] : ["latest"],
1434
1403
  testFileMatch: ["**/*.tst.*", "**/__typetests__/*.test.*", "**/typetests/*.test.*"],
1435
1404
  tsconfig: "findup",
1436
1405
  };
1437
1406
 
1438
1407
  class Config {
1439
- static #onDiagnostics(diagnostics) {
1440
- EventEmitter.dispatch(["config:error", { diagnostics: [diagnostics] }]);
1408
+ static #onDiagnostics(diagnostic) {
1409
+ EventEmitter.dispatch(["config:error", { diagnostics: [diagnostic] }]);
1441
1410
  }
1442
1411
  static async parseCommandLine(commandLine) {
1443
1412
  const commandLineOptions = {};
@@ -1492,6 +1461,7 @@ var OptionGroup;
1492
1461
  (function (OptionGroup) {
1493
1462
  OptionGroup[OptionGroup["CommandLine"] = 2] = "CommandLine";
1494
1463
  OptionGroup[OptionGroup["ConfigFile"] = 4] = "ConfigFile";
1464
+ OptionGroup[OptionGroup["ResolvedConfig"] = 6] = "ResolvedConfig";
1495
1465
  })(OptionGroup || (OptionGroup = {}));
1496
1466
 
1497
1467
  class CancellationHandler {
@@ -1837,25 +1807,6 @@ class ResultHandler {
1837
1807
  }
1838
1808
  }
1839
1809
 
1840
- class HooksService {
1841
- static #handlers = new Set();
1842
- static addHandler(hooks) {
1843
- HooksService.#handlers.add(hooks);
1844
- }
1845
- static async call(hook, options) {
1846
- for (const handler of HooksService.#handlers) {
1847
- const result = await handler[hook]?.(options);
1848
- if (result != null) {
1849
- options = result;
1850
- }
1851
- }
1852
- return options;
1853
- }
1854
- static removeHandlers() {
1855
- HooksService.#handlers.clear();
1856
- }
1857
- }
1858
-
1859
1810
  function jsx(type, props) {
1860
1811
  return { props, type };
1861
1812
  }
@@ -2237,6 +2188,25 @@ function watchUsageText() {
2237
2188
  return jsx(Text, { children: usageText });
2238
2189
  }
2239
2190
 
2191
+ class PluginService {
2192
+ static #handlers = new Map();
2193
+ static addHandler(plugin) {
2194
+ PluginService.#handlers.set(plugin.name, plugin);
2195
+ }
2196
+ static async call(hook, argument, context) {
2197
+ let result = argument;
2198
+ for (const [, plugin] of PluginService.#handlers) {
2199
+ if (hook in plugin) {
2200
+ result = await plugin[hook].call(context, result);
2201
+ }
2202
+ }
2203
+ return result;
2204
+ }
2205
+ static removeHandlers() {
2206
+ PluginService.#handlers.clear();
2207
+ }
2208
+ }
2209
+
2240
2210
  class BaseReporter {
2241
2211
  resolvedConfig;
2242
2212
  constructor(resolvedConfig) {
@@ -3781,7 +3751,7 @@ class ToRaiseError {
3781
3751
  if (this.#compiler.isStringLiteralLike(targetNode)) {
3782
3752
  return this.#compiler.flattenDiagnosticMessageText(diagnostic.messageText, " ", 0).includes(targetNode.text);
3783
3753
  }
3784
- return Number.parseInt(targetNode.text) === diagnostic.code;
3754
+ return Number.parseInt(targetNode.text, 10) === diagnostic.code;
3785
3755
  }
3786
3756
  }
3787
3757
 
@@ -4126,7 +4096,7 @@ class TaskRunner {
4126
4096
  class Runner {
4127
4097
  #eventEmitter = new EventEmitter();
4128
4098
  #resolvedConfig;
4129
- static version = "3.0.0-beta.5";
4099
+ static version = "3.0.0-rc.0";
4130
4100
  constructor(resolvedConfig) {
4131
4101
  this.#resolvedConfig = resolvedConfig;
4132
4102
  }
@@ -4250,11 +4220,11 @@ class Cli {
4250
4220
  }
4251
4221
  continue;
4252
4222
  }
4253
- for (const plugin of resolvedConfig.plugins) {
4254
- const hooks = (await import(plugin)).default;
4255
- HooksService.addHandler(hooks);
4223
+ for (const pluginSpecifier of resolvedConfig.plugins) {
4224
+ const plugin = (await import(pluginSpecifier)).default;
4225
+ PluginService.addHandler(plugin);
4256
4226
  }
4257
- resolvedConfig = await HooksService.call("config", resolvedConfig);
4227
+ resolvedConfig = await PluginService.call("config", resolvedConfig, {});
4258
4228
  if (commandLine.includes("--showConfig")) {
4259
4229
  OutputService.writeMessage(formattedText({ ...resolvedConfig, ...environmentOptions }));
4260
4230
  continue;
@@ -4275,7 +4245,7 @@ class Cli {
4275
4245
  continue;
4276
4246
  }
4277
4247
  }
4278
- testFiles = await HooksService.call("select", testFiles);
4248
+ testFiles = await PluginService.call("select", testFiles, { resolvedConfig });
4279
4249
  if (commandLine.includes("--listFiles")) {
4280
4250
  OutputService.writeMessage(formattedText(testFiles.map((testFile) => testFile.toString())));
4281
4251
  continue;
@@ -4284,7 +4254,7 @@ class Cli {
4284
4254
  this.#eventEmitter.removeReporter(setupReporter);
4285
4255
  const runner = new Runner(resolvedConfig);
4286
4256
  await runner.run(testFiles, cancellationToken);
4287
- HooksService.removeHandlers();
4257
+ PluginService.removeHandlers();
4288
4258
  } while (cancellationToken.reason === "configChange");
4289
4259
  this.#eventEmitter.removeHandlers();
4290
4260
  }
@@ -4316,4 +4286,4 @@ class Cli {
4316
4286
  }
4317
4287
  }
4318
4288
 
4319
- export { Assertion, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, HooksService, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectResult, ProjectService, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, Version, WatchReporter, WatchService, Watcher, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
4289
+ export { Assertion, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, ProjectService, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, Version, WatchReporter, WatchService, Watcher, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "3.0.0-beta.5",
3
+ "version": "3.0.0-rc.0",
4
4
  "description": "The Essential Type Testing Tool.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -63,14 +63,14 @@
63
63
  "devDependencies": {
64
64
  "@biomejs/biome": "1.9.4",
65
65
  "@rollup/plugin-typescript": "12.1.1",
66
- "@types/node": "20.16.14",
67
- "@types/react": "18.3.11",
66
+ "@types/node": "22.8.4",
67
+ "@types/react": "18.3.12",
68
68
  "ajv": "8.17.1",
69
69
  "cspell": "8.15.4",
70
70
  "magic-string": "0.30.12",
71
71
  "monocart-coverage-reports": "2.11.1",
72
72
  "pretty-ansi": "2.0.0",
73
- "rollup": "4.24.0",
73
+ "rollup": "4.24.3",
74
74
  "rollup-plugin-dts": "6.1.1",
75
75
  "tslib": "2.8.0",
76
76
  "typescript": "5.6.3"
@@ -85,6 +85,6 @@
85
85
  },
86
86
  "packageManager": "yarn@4.5.1",
87
87
  "engines": {
88
- "node": ">=18.17"
88
+ "node": ">=18.19"
89
89
  }
90
90
  }