tstyche 4.0.0-beta.7 → 4.0.0-beta.9

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.
@@ -3,7 +3,6 @@ import type ts from 'typescript';
3
3
  declare enum CancellationReason {
4
4
  ConfigChange = "configChange",
5
5
  ConfigError = "configError",
6
- CollectError = "collectError",
7
6
  FailFast = "failFast",
8
7
  WatchClose = "watchClose"
9
8
  }
@@ -21,58 +20,6 @@ declare class Cli {
21
20
  run(commandLine: Array<string>, cancellationToken?: CancellationToken): Promise<void>;
22
21
  }
23
22
 
24
- declare enum DiagnosticCategory {
25
- Error = "error",
26
- Warning = "warning"
27
- }
28
-
29
- declare class SourceFile {
30
- #private;
31
- fileName: string;
32
- text: string;
33
- constructor(fileName: string, text: string);
34
- getLineStarts(): Array<number>;
35
- getLineAndCharacterOfPosition(position: number): {
36
- line: number;
37
- character: number;
38
- };
39
- }
40
-
41
- declare class DiagnosticOrigin {
42
- assertion: AssertionNode | undefined;
43
- end: number;
44
- sourceFile: SourceFile | ts.SourceFile;
45
- start: number;
46
- constructor(start: number, end: number, sourceFile: SourceFile | ts.SourceFile, assertion?: AssertionNode);
47
- static fromAssertion(assertion: AssertionNode): DiagnosticOrigin;
48
- static fromNode(node: ts.Node, assertion?: AssertionNode): DiagnosticOrigin;
49
- static fromNodes(nodes: ts.NodeArray<ts.Node>, assertion?: AssertionNode): DiagnosticOrigin;
50
- }
51
-
52
- declare class Diagnostic {
53
- category: DiagnosticCategory;
54
- code: string | undefined;
55
- origin: DiagnosticOrigin | undefined;
56
- related: Array<Diagnostic> | undefined;
57
- text: string | Array<string>;
58
- constructor(text: string | Array<string>, category: DiagnosticCategory, origin?: DiagnosticOrigin);
59
- add(options: {
60
- code?: string | undefined;
61
- related?: Array<Diagnostic> | undefined;
62
- }): this;
63
- static error(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
64
- extendWith(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
65
- static fromDiagnostics(diagnostics: Array<ts.Diagnostic>): Array<Diagnostic>;
66
- static warning(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
67
- }
68
-
69
- declare function diagnosticBelongsToNode(diagnostic: ts.Diagnostic, node: ts.NodeArray<ts.Node> | ts.Node): boolean;
70
- declare function getDiagnosticMessageText(diagnostic: ts.Diagnostic): string | Array<string>;
71
- declare function getTextSpanEnd(span: ts.TextSpan): number;
72
- declare function isDiagnosticWithLocation(diagnostic: ts.Diagnostic): diagnostic is ts.DiagnosticWithLocation;
73
-
74
- type DiagnosticsHandler<T extends Diagnostic | Array<Diagnostic> = Diagnostic> = (this: void, diagnostics: T) => void;
75
-
76
23
  declare enum TestTreeNodeBrand {
77
24
  Describe = "describe",
78
25
  Test = "test",
@@ -88,21 +35,27 @@ declare enum TestTreeNodeFlags {
88
35
  Todo = 8
89
36
  }
90
37
 
38
+ declare class WhenNode extends TestTreeNode {
39
+ actionNode: ts.CallExpression;
40
+ actionNameNode: ts.PropertyAccessExpression;
41
+ abilityDiagnostics: Set<ts.Diagnostic> | undefined;
42
+ target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
43
+ constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
44
+ }
45
+
91
46
  declare class TestTreeNode {
92
- #private;
93
47
  brand: TestTreeNodeBrand;
94
- children: Array<TestTreeNode | AssertionNode>;
48
+ children: Array<TestTreeNode | AssertionNode | WhenNode>;
95
49
  diagnostics: Set<ts.Diagnostic>;
96
50
  flags: TestTreeNodeFlags;
97
51
  name: string;
98
52
  node: ts.CallExpression;
99
53
  parent: TestTree | TestTreeNode;
100
54
  constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags);
101
- validate(): Array<Diagnostic>;
102
55
  }
103
56
 
104
57
  declare class TestTree {
105
- children: Array<TestTreeNode | AssertionNode>;
58
+ children: Array<TestTreeNode | AssertionNode | WhenNode>;
106
59
  diagnostics: Set<ts.Diagnostic>;
107
60
  hasOnly: boolean;
108
61
  sourceFile: ts.SourceFile;
@@ -296,6 +249,58 @@ declare class Config {
296
249
  static resolveConfigFilePath(filePath?: string): string;
297
250
  }
298
251
 
252
+ declare enum DiagnosticCategory {
253
+ Error = "error",
254
+ Warning = "warning"
255
+ }
256
+
257
+ declare class SourceFile {
258
+ #private;
259
+ fileName: string;
260
+ text: string;
261
+ constructor(fileName: string, text: string);
262
+ getLineStarts(): Array<number>;
263
+ getLineAndCharacterOfPosition(position: number): {
264
+ line: number;
265
+ character: number;
266
+ };
267
+ }
268
+
269
+ declare class DiagnosticOrigin {
270
+ assertion: AssertionNode | undefined;
271
+ end: number;
272
+ sourceFile: SourceFile | ts.SourceFile;
273
+ start: number;
274
+ constructor(start: number, end: number, sourceFile: SourceFile | ts.SourceFile, assertion?: AssertionNode);
275
+ static fromAssertion(assertion: AssertionNode): DiagnosticOrigin;
276
+ static fromNode(node: ts.Node, assertion?: AssertionNode): DiagnosticOrigin;
277
+ static fromNodes(nodes: ts.NodeArray<ts.Node>, assertion?: AssertionNode): DiagnosticOrigin;
278
+ }
279
+
280
+ declare class Diagnostic {
281
+ category: DiagnosticCategory;
282
+ code: string | undefined;
283
+ origin: DiagnosticOrigin | undefined;
284
+ related: Array<Diagnostic> | undefined;
285
+ text: string | Array<string>;
286
+ constructor(text: string | Array<string>, category: DiagnosticCategory, origin?: DiagnosticOrigin);
287
+ add(options: {
288
+ code?: string | undefined;
289
+ related?: Array<Diagnostic> | undefined;
290
+ }): this;
291
+ static error(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
292
+ extendWith(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
293
+ static fromDiagnostics(diagnostics: Array<ts.Diagnostic>): Array<Diagnostic>;
294
+ static warning(text: string | Array<string>, origin?: DiagnosticOrigin): Diagnostic;
295
+ }
296
+
297
+ declare function diagnosticBelongsToNode(diagnostic: ts.Diagnostic, node: ts.NodeArray<ts.Node> | ts.Node): boolean;
298
+ declare function getDiagnosticMessageText(diagnostic: ts.Diagnostic): string | Array<string>;
299
+ declare function getTextSpanEnd(span: ts.TextSpan): number;
300
+ declare function isDiagnosticWithLocation(diagnostic: ts.Diagnostic): diagnostic is ts.DiagnosticWithLocation;
301
+
302
+ type DiagnosticsHandler<T extends Diagnostic | Array<Diagnostic> = Diagnostic> = (this: void, diagnostics: T) => void;
303
+
299
304
  declare enum OptionGroup {
300
305
  CommandLine = 2,
301
306
  ConfigFile = 4,
@@ -346,13 +351,9 @@ declare class CollectService {
346
351
 
347
352
  declare function nodeBelongsToArgumentList(compiler: typeof ts, node: ts.Node): boolean;
348
353
 
349
- declare class WhenNode extends TestTreeNode {
350
- actionNode: ts.CallExpression;
351
- actionNameNode: ts.PropertyAccessExpression;
352
- abilityDiagnostics: Set<ts.Diagnostic> | undefined;
353
- target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
354
- constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
355
- }
354
+ declare function argumentIsProvided<T>(argumentNameText: string, node: T, enclosingNode: ts.Node, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>): node is NonNullable<T>;
355
+
356
+ declare function argumentOrTypeArgumentIsProvided<T>(argumentNameText: string, typeArgumentNameText: string, node: T, enclosingNode: ts.Node, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>): node is NonNullable<T>;
356
357
 
357
358
  interface EnvironmentOptions {
358
359
  /**
@@ -599,6 +600,12 @@ declare class EventEmitter {
599
600
  removeReporters(): void;
600
601
  }
601
602
 
603
+ declare class Reject {
604
+ #private;
605
+ constructor(compiler: typeof ts, typeChecker: ts.TypeChecker, resolvedConfig: ResolvedConfig);
606
+ argumentType(target: Array<[name: string, node: ts.Expression | ts.TypeNode | undefined]>, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>): boolean;
607
+ }
608
+
602
609
  interface MatchResult {
603
610
  explain: () => Array<Diagnostic>;
604
611
  isMatch: boolean;
@@ -624,7 +631,7 @@ declare class ExpectService {
624
631
  private toBeConstructableWith;
625
632
  private toHaveProperty;
626
633
  private toRaiseError;
627
- constructor(compiler: typeof ts, typeChecker: TypeChecker, resolvedConfig: ResolvedConfig);
634
+ constructor(compiler: typeof ts, typeChecker: TypeChecker, reject: Reject);
628
635
  match(assertion: AssertionNode, onDiagnostics: DiagnosticsHandler<Diagnostic | Array<Diagnostic>>): MatchResult | undefined;
629
636
  }
630
637
 
@@ -878,5 +885,11 @@ declare class WatchService {
878
885
  watch(cancellationToken: CancellationToken): AsyncIterable<Array<Task>>;
879
886
  }
880
887
 
881
- export { AssertionNode, 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, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
888
+ declare class WhenService {
889
+ #private;
890
+ constructor(reject: Reject, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>);
891
+ action(when: WhenNode): void;
892
+ }
893
+
894
+ export { AssertionNode, 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, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
882
895
  export type { CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, EnvironmentOptions, Event, EventHandler, FileWatchHandler, InputHandler, ItemDefinition, MatchResult, OptionDefinition, Plugin, Reporter, ReporterEvent, ResolvedConfig, ScribblerOptions, SelectHookContext, TargetResultStatus, TaskResultStatus, TypeChecker, WatchHandler, WatcherOptions };
package/build/tstyche.js CHANGED
@@ -572,7 +572,6 @@ class ManifestService {
572
572
  #manifestFilePath;
573
573
  #npmRegistry;
574
574
  #storePath;
575
- #supportedVersionRegex = /^(5)\.\d\.\d$/;
576
575
  constructor(storePath, npmRegistry, fetcher) {
577
576
  this.#storePath = storePath;
578
577
  this.#npmRegistry = npmRegistry;
@@ -602,7 +601,7 @@ class ManifestService {
602
601
  const versions = [];
603
602
  const packageMetadata = (await response.json());
604
603
  for (const [tag, meta] of Object.entries(packageMetadata.versions)) {
605
- if (this.#supportedVersionRegex.test(tag)) {
604
+ if (!tag.includes("-") && Version.isSatisfiedWith(tag, "4.7.2")) {
606
605
  versions.push(tag);
607
606
  packages[tag] = { integrity: meta.dist.integrity, tarball: meta.dist.tarball };
608
607
  }
@@ -701,6 +700,9 @@ class PackageService {
701
700
  if (response?.body != null) {
702
701
  const targetPath = `${packagePath}-${Math.random().toString(32).slice(2)}`;
703
702
  for await (const file of TarReader.extract(response.body)) {
703
+ if (!file.name.startsWith("package/")) {
704
+ continue;
705
+ }
704
706
  const filePath = Path.join(targetPath, file.name.replace("package/", ""));
705
707
  const directoryPath = Path.dirname(filePath);
706
708
  if (!existsSync(directoryPath)) {
@@ -2547,7 +2549,6 @@ var CancellationReason;
2547
2549
  (function (CancellationReason) {
2548
2550
  CancellationReason["ConfigChange"] = "configChange";
2549
2551
  CancellationReason["ConfigError"] = "configError";
2550
- CancellationReason["CollectError"] = "collectError";
2551
2552
  CancellationReason["FailFast"] = "failFast";
2552
2553
  CancellationReason["WatchClose"] = "watchClose";
2553
2554
  })(CancellationReason || (CancellationReason = {}));
@@ -2873,18 +2874,9 @@ class WatchService {
2873
2874
  }
2874
2875
  }
2875
2876
 
2876
- var TestTreeNodeBrand;
2877
- (function (TestTreeNodeBrand) {
2878
- TestTreeNodeBrand["Describe"] = "describe";
2879
- TestTreeNodeBrand["Test"] = "test";
2880
- TestTreeNodeBrand["Expect"] = "expect";
2881
- TestTreeNodeBrand["When"] = "when";
2882
- })(TestTreeNodeBrand || (TestTreeNodeBrand = {}));
2883
-
2884
2877
  class TestTreeNode {
2885
2878
  brand;
2886
2879
  children = [];
2887
- #compiler;
2888
2880
  diagnostics = new Set();
2889
2881
  flags;
2890
2882
  name = "";
@@ -2892,7 +2884,6 @@ class TestTreeNode {
2892
2884
  parent;
2893
2885
  constructor(compiler, brand, node, parent, flags) {
2894
2886
  this.brand = brand;
2895
- this.#compiler = compiler;
2896
2887
  this.node = node;
2897
2888
  this.parent = parent;
2898
2889
  this.flags = flags;
@@ -2908,34 +2899,6 @@ class TestTreeNode {
2908
2899
  }
2909
2900
  }
2910
2901
  }
2911
- validate() {
2912
- const diagnostics = [];
2913
- const getText = (node) => `'${node.expression.getText()}()' cannot be nested within '${this.node.expression.getText()}()'.`;
2914
- const getParentCallExpression = (node) => {
2915
- while (!this.#compiler.isCallExpression(node.parent)) {
2916
- node = node.parent;
2917
- }
2918
- return node.parent;
2919
- };
2920
- switch (this.brand) {
2921
- case TestTreeNodeBrand.Describe:
2922
- for (const child of this.children) {
2923
- if (child.brand === TestTreeNodeBrand.Expect || child.brand === TestTreeNodeBrand.When) {
2924
- diagnostics.push(Diagnostic.error(getText(child.node), DiagnosticOrigin.fromNode(getParentCallExpression(child.node))));
2925
- }
2926
- }
2927
- break;
2928
- case TestTreeNodeBrand.Test:
2929
- case TestTreeNodeBrand.Expect:
2930
- for (const child of this.children) {
2931
- if (child.brand === TestTreeNodeBrand.Describe || child.brand === TestTreeNodeBrand.Test) {
2932
- diagnostics.push(Diagnostic.error(getText(child.node), DiagnosticOrigin.fromNode(child.node)));
2933
- }
2934
- }
2935
- break;
2936
- }
2937
- return diagnostics;
2938
- }
2939
2902
  }
2940
2903
 
2941
2904
  class AssertionNode extends TestTreeNode {
@@ -3033,6 +2996,11 @@ class AbilityLayer {
3033
2996
  this.#nodes = [];
3034
2997
  this.#text = "";
3035
2998
  }
2999
+ #eraseTrailingComma(node, parent) {
3000
+ if (node.hasTrailingComma) {
3001
+ this.#addRanges(parent, [{ start: node.end - 1, end: node.end }]);
3002
+ }
3003
+ }
3036
3004
  handleWhen(whenNode) {
3037
3005
  const whenStart = whenNode.node.getStart();
3038
3006
  const whenExpressionEnd = whenNode.node.expression.getEnd();
@@ -3040,13 +3008,14 @@ class AbilityLayer {
3040
3008
  const actionNameEnd = whenNode.actionNameNode.getEnd();
3041
3009
  switch (whenNode.actionNameNode.name.text) {
3042
3010
  case "isCalledWith":
3011
+ this.#eraseTrailingComma(whenNode.target, whenNode);
3043
3012
  this.#addRanges(whenNode, [
3044
3013
  {
3045
- end: whenExpressionEnd,
3046
3014
  start: whenStart,
3015
+ end: whenExpressionEnd,
3047
3016
  replacement: nodeBelongsToArgumentList(this.#compiler, whenNode.actionNode) ? "" : ";",
3048
3017
  },
3049
- { end: actionNameEnd, start: whenEnd },
3018
+ { start: whenEnd, end: actionNameEnd },
3050
3019
  ]);
3051
3020
  break;
3052
3021
  }
@@ -3059,28 +3028,30 @@ class AbilityLayer {
3059
3028
  switch (assertionNode.matcherNameNode.name.text) {
3060
3029
  case "toBeApplicable":
3061
3030
  this.#addRanges(assertionNode, [
3062
- { end: expectExpressionEnd, start: expectStart },
3063
- { end: matcherNameEnd, start: expectEnd },
3031
+ { start: expectStart, end: expectExpressionEnd },
3032
+ { start: expectEnd, end: matcherNameEnd },
3064
3033
  ]);
3065
3034
  break;
3066
3035
  case "toBeCallableWith":
3036
+ this.#eraseTrailingComma(assertionNode.source, assertionNode);
3067
3037
  this.#addRanges(assertionNode, [
3068
3038
  {
3069
- end: expectExpressionEnd,
3070
3039
  start: expectStart,
3040
+ end: expectExpressionEnd,
3071
3041
  replacement: nodeBelongsToArgumentList(this.#compiler, assertionNode.matcherNode) ? "" : ";",
3072
3042
  },
3073
- { end: matcherNameEnd, start: expectEnd },
3043
+ { start: expectEnd, end: matcherNameEnd },
3074
3044
  ]);
3075
3045
  break;
3076
3046
  case "toBeConstructableWith":
3047
+ this.#eraseTrailingComma(assertionNode.source, assertionNode);
3077
3048
  this.#addRanges(assertionNode, [
3078
3049
  {
3079
- end: expectExpressionEnd,
3080
3050
  start: expectStart,
3051
+ end: expectExpressionEnd,
3081
3052
  replacement: nodeBelongsToArgumentList(this.#compiler, assertionNode.matcherNode) ? "new" : "; new",
3082
3053
  },
3083
- { end: matcherNameEnd, start: expectEnd },
3054
+ { start: expectEnd, end: matcherNameEnd },
3084
3055
  ]);
3085
3056
  break;
3086
3057
  }
@@ -3097,6 +3068,14 @@ class CollectDiagnosticText {
3097
3068
  }
3098
3069
  }
3099
3070
 
3071
+ var TestTreeNodeBrand;
3072
+ (function (TestTreeNodeBrand) {
3073
+ TestTreeNodeBrand["Describe"] = "describe";
3074
+ TestTreeNodeBrand["Test"] = "test";
3075
+ TestTreeNodeBrand["Expect"] = "expect";
3076
+ TestTreeNodeBrand["When"] = "when";
3077
+ })(TestTreeNodeBrand || (TestTreeNodeBrand = {}));
3078
+
3100
3079
  var TestTreeNodeFlags;
3101
3080
  (function (TestTreeNodeFlags) {
3102
3081
  TestTreeNodeFlags[TestTreeNodeFlags["None"] = 0] = "None";
@@ -3110,19 +3089,8 @@ class IdentifierLookup {
3110
3089
  #compiler;
3111
3090
  #identifiers;
3112
3091
  #moduleSpecifiers = ['"tstyche"', "'tstyche'"];
3113
- constructor(compiler, identifiers) {
3092
+ constructor(compiler) {
3114
3093
  this.#compiler = compiler;
3115
- this.#identifiers = identifiers ?? {
3116
- namedImports: {
3117
- describe: undefined,
3118
- expect: undefined,
3119
- it: undefined,
3120
- namespace: undefined,
3121
- test: undefined,
3122
- when: undefined,
3123
- },
3124
- namespace: undefined,
3125
- };
3126
3094
  }
3127
3095
  handleImportDeclaration(node) {
3128
3096
  if (this.#moduleSpecifiers.includes(node.moduleSpecifier.getText()) &&
@@ -3150,7 +3118,20 @@ class IdentifierLookup {
3150
3118
  }
3151
3119
  }
3152
3120
  }
3153
- resolveTestMemberMeta(node) {
3121
+ open() {
3122
+ this.#identifiers = {
3123
+ namedImports: {
3124
+ describe: undefined,
3125
+ expect: undefined,
3126
+ it: undefined,
3127
+ namespace: undefined,
3128
+ test: undefined,
3129
+ when: undefined,
3130
+ },
3131
+ namespace: undefined,
3132
+ };
3133
+ }
3134
+ resolveTestTreeNodeMeta(node) {
3154
3135
  let flags = TestTreeNodeFlags.None;
3155
3136
  let expression = node.expression;
3156
3137
  while (this.#compiler.isPropertyAccessExpression(expression)) {
@@ -3173,27 +3154,27 @@ class IdentifierLookup {
3173
3154
  }
3174
3155
  expression = expression.expression;
3175
3156
  }
3176
- let identifierName;
3157
+ let identifier;
3177
3158
  if (this.#compiler.isPropertyAccessExpression(expression) &&
3178
3159
  expression.expression.getText() === this.#identifiers.namespace) {
3179
- identifierName = expression.name.getText();
3160
+ identifier = expression.name.getText();
3180
3161
  }
3181
3162
  else {
3182
- identifierName = Object.keys(this.#identifiers.namedImports).find((key) => this.#identifiers.namedImports[key] === expression.getText());
3163
+ identifier = Object.keys(this.#identifiers.namedImports).find((key) => this.#identifiers.namedImports[key] === expression.getText());
3183
3164
  }
3184
- if (!identifierName) {
3165
+ if (!identifier) {
3185
3166
  return;
3186
3167
  }
3187
- switch (identifierName) {
3168
+ switch (identifier) {
3188
3169
  case "describe":
3189
- return { brand: TestTreeNodeBrand.Describe, flags };
3170
+ return { brand: TestTreeNodeBrand.Describe, flags, identifier };
3190
3171
  case "it":
3191
3172
  case "test":
3192
- return { brand: TestTreeNodeBrand.Test, flags };
3173
+ return { brand: TestTreeNodeBrand.Test, flags, identifier };
3193
3174
  case "expect":
3194
- return { brand: TestTreeNodeBrand.Expect, flags };
3175
+ return { brand: TestTreeNodeBrand.Expect, flags, identifier };
3195
3176
  case "when":
3196
- return { brand: TestTreeNodeBrand.When, flags };
3177
+ return { brand: TestTreeNodeBrand.When, flags, identifier };
3197
3178
  }
3198
3179
  return;
3199
3180
  }
@@ -3232,92 +3213,119 @@ class WhenNode extends TestTreeNode {
3232
3213
  class CollectService {
3233
3214
  #abilityLayer;
3234
3215
  #compiler;
3235
- #projectService;
3236
- #resolvedConfig;
3237
- #testTree;
3216
+ #identifierLookup;
3238
3217
  constructor(compiler, projectService, resolvedConfig) {
3239
3218
  this.#compiler = compiler;
3240
- this.#projectService = projectService;
3241
- this.#resolvedConfig = resolvedConfig;
3242
- this.#abilityLayer = new AbilityLayer(compiler, this.#projectService, this.#resolvedConfig);
3219
+ this.#abilityLayer = new AbilityLayer(compiler, projectService, resolvedConfig);
3220
+ this.#identifierLookup = new IdentifierLookup(compiler);
3243
3221
  }
3244
- #collectTestTreeNodes(node, identifiers, parent) {
3222
+ #collectTestTreeNodes(node, parent, testTree) {
3245
3223
  if (this.#compiler.isCallExpression(node)) {
3246
- const meta = identifiers.resolveTestMemberMeta(node);
3247
- if (meta != null && (meta.brand === TestTreeNodeBrand.Describe || meta.brand === TestTreeNodeBrand.Test)) {
3248
- const testTreeNode = new TestTreeNode(this.#compiler, meta.brand, node, parent, meta.flags);
3249
- this.#compiler.forEachChild(node, (node) => {
3250
- this.#collectTestTreeNodes(node, identifiers, testTreeNode);
3251
- });
3252
- this.#onNode(testTreeNode, parent);
3253
- return;
3254
- }
3255
- if (meta != null && meta.brand === TestTreeNodeBrand.Expect) {
3256
- const modifierNode = this.#getChainedNode(node, "type");
3257
- if (!modifierNode) {
3224
+ const meta = this.#identifierLookup.resolveTestTreeNodeMeta(node);
3225
+ if (meta != null) {
3226
+ if (!this.#checkNode(node, meta, parent)) {
3258
3227
  return;
3259
3228
  }
3260
- const notNode = this.#getChainedNode(modifierNode, "not");
3261
- const matcherNameNode = this.#getChainedNode(notNode ?? modifierNode);
3262
- if (!matcherNameNode) {
3263
- return;
3264
- }
3265
- const matcherNode = this.#getMatcherNode(matcherNameNode);
3266
- if (!matcherNode) {
3229
+ if (meta.brand === TestTreeNodeBrand.Describe || meta.brand === TestTreeNodeBrand.Test) {
3230
+ const testTreeNode = new TestTreeNode(this.#compiler, meta.brand, node, parent, meta.flags);
3231
+ this.#compiler.forEachChild(node, (node) => {
3232
+ this.#collectTestTreeNodes(node, testTreeNode, testTree);
3233
+ });
3234
+ this.#onNode(testTreeNode, parent, testTree);
3267
3235
  return;
3268
3236
  }
3269
- const assertionNode = new AssertionNode(this.#compiler, meta.brand, node, parent, meta.flags, matcherNode, matcherNameNode, modifierNode, notNode);
3270
- this.#abilityLayer.handleAssertion(assertionNode);
3271
- this.#compiler.forEachChild(node, (node) => {
3272
- this.#collectTestTreeNodes(node, identifiers, assertionNode);
3273
- });
3274
- this.#onNode(assertionNode, parent);
3275
- return;
3276
- }
3277
- if (meta != null && meta.brand === TestTreeNodeBrand.When) {
3278
- const actionNameNode = this.#getChainedNode(node);
3279
- if (!actionNameNode) {
3237
+ if (meta.brand === TestTreeNodeBrand.Expect) {
3238
+ const modifierNode = this.#getChainedNode(node, "type");
3239
+ if (!modifierNode) {
3240
+ return;
3241
+ }
3242
+ const notNode = this.#getChainedNode(modifierNode, "not");
3243
+ const matcherNameNode = this.#getChainedNode(notNode ?? modifierNode);
3244
+ if (!matcherNameNode) {
3245
+ return;
3246
+ }
3247
+ const matcherNode = this.#getMatcherNode(matcherNameNode);
3248
+ if (!matcherNode) {
3249
+ return;
3250
+ }
3251
+ const assertionNode = new AssertionNode(this.#compiler, meta.brand, node, parent, meta.flags, matcherNode, matcherNameNode, modifierNode, notNode);
3252
+ this.#abilityLayer.handleAssertion(assertionNode);
3253
+ this.#compiler.forEachChild(node, (node) => {
3254
+ this.#collectTestTreeNodes(node, assertionNode, testTree);
3255
+ });
3256
+ this.#onNode(assertionNode, parent, testTree);
3280
3257
  return;
3281
3258
  }
3282
- const actionNode = this.#getActionNode(actionNameNode);
3283
- if (!actionNode) {
3259
+ if (meta.brand === TestTreeNodeBrand.When) {
3260
+ const actionNameNode = this.#getChainedNode(node);
3261
+ if (!actionNameNode) {
3262
+ return;
3263
+ }
3264
+ const actionNode = this.#getActionNode(actionNameNode);
3265
+ if (!actionNode) {
3266
+ return;
3267
+ }
3268
+ this.#compiler.forEachChild(actionNode, (node) => {
3269
+ if (this.#compiler.isCallExpression(node)) {
3270
+ const meta = this.#identifierLookup.resolveTestTreeNodeMeta(node);
3271
+ if (meta?.brand === TestTreeNodeBrand.Describe || meta?.brand === TestTreeNodeBrand.Test) {
3272
+ const text = CollectDiagnosticText.cannotBeNestedWithin(meta.identifier, "when");
3273
+ const origin = DiagnosticOrigin.fromNode(node);
3274
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3275
+ }
3276
+ }
3277
+ });
3278
+ const whenNode = new WhenNode(this.#compiler, meta.brand, node, parent, meta.flags, actionNode, actionNameNode);
3279
+ this.#abilityLayer.handleWhen(whenNode);
3280
+ this.#onNode(whenNode, parent, testTree);
3284
3281
  return;
3285
3282
  }
3286
- this.#compiler.forEachChild(actionNode, (node) => {
3287
- if (this.#compiler.isCallExpression(node)) {
3288
- const meta = identifiers.resolveTestMemberMeta(node);
3289
- if (meta != null && (meta.brand === TestTreeNodeBrand.Describe || meta.brand === TestTreeNodeBrand.Test)) {
3290
- const text = CollectDiagnosticText.cannotBeNestedWithin(node.expression.getText(), "when");
3291
- const origin = DiagnosticOrigin.fromNode(node);
3292
- this.#onDiagnostics(Diagnostic.error(text, origin));
3293
- }
3294
- }
3295
- });
3296
- const whenNode = new WhenNode(this.#compiler, meta.brand, node, parent, meta.flags, actionNode, actionNameNode);
3297
- this.#abilityLayer.handleWhen(whenNode);
3298
- this.#onNode(whenNode, parent);
3299
- return;
3300
3283
  }
3301
3284
  }
3302
3285
  if (this.#compiler.isImportDeclaration(node)) {
3303
- identifiers.handleImportDeclaration(node);
3286
+ this.#identifierLookup.handleImportDeclaration(node);
3304
3287
  return;
3305
3288
  }
3306
3289
  this.#compiler.forEachChild(node, (node) => {
3307
- this.#collectTestTreeNodes(node, identifiers, parent);
3290
+ this.#collectTestTreeNodes(node, parent, testTree);
3308
3291
  });
3309
3292
  }
3310
3293
  createTestTree(sourceFile, semanticDiagnostics = []) {
3311
3294
  const testTree = new TestTree(new Set(semanticDiagnostics), sourceFile);
3312
3295
  EventEmitter.dispatch(["collect:start", { tree: testTree }]);
3313
- this.#testTree = testTree;
3314
3296
  this.#abilityLayer.open(sourceFile);
3315
- this.#collectTestTreeNodes(sourceFile, new IdentifierLookup(this.#compiler), testTree);
3297
+ this.#identifierLookup.open();
3298
+ this.#collectTestTreeNodes(sourceFile, testTree, testTree);
3316
3299
  this.#abilityLayer.close();
3317
- this.#testTree = undefined;
3318
3300
  EventEmitter.dispatch(["collect:end", { tree: testTree }]);
3319
3301
  return testTree;
3320
3302
  }
3303
+ #checkNode(node, meta, parent) {
3304
+ if ("brand" in parent && !this.#isNodeAllowed(meta, parent)) {
3305
+ const text = CollectDiagnosticText.cannotBeNestedWithin(meta.identifier, parent.node.expression.getText());
3306
+ const origin = DiagnosticOrigin.fromNode(node);
3307
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3308
+ return false;
3309
+ }
3310
+ return true;
3311
+ }
3312
+ #isNodeAllowed(meta, parent) {
3313
+ switch (meta.brand) {
3314
+ case TestTreeNodeBrand.Describe:
3315
+ case TestTreeNodeBrand.Test:
3316
+ if (parent.brand === TestTreeNodeBrand.Test || parent.brand === TestTreeNodeBrand.Expect) {
3317
+ return false;
3318
+ }
3319
+ break;
3320
+ case TestTreeNodeBrand.Expect:
3321
+ case TestTreeNodeBrand.When:
3322
+ if (parent.brand === TestTreeNodeBrand.Describe) {
3323
+ return false;
3324
+ }
3325
+ break;
3326
+ }
3327
+ return true;
3328
+ }
3321
3329
  #getChainedNode({ parent }, name) {
3322
3330
  if (!this.#compiler.isPropertyAccessExpression(parent)) {
3323
3331
  return;
@@ -3348,10 +3356,10 @@ class CollectService {
3348
3356
  #onDiagnostics(diagnostic) {
3349
3357
  EventEmitter.dispatch(["collect:error", { diagnostics: [diagnostic] }]);
3350
3358
  }
3351
- #onNode(node, parent) {
3359
+ #onNode(node, parent, testTree) {
3352
3360
  parent.children.push(node);
3353
3361
  if (node.flags & TestTreeNodeFlags.Only) {
3354
- this.#testTree.hasOnly = true;
3362
+ testTree.hasOnly = true;
3355
3363
  }
3356
3364
  EventEmitter.dispatch(["collect:node", { node }]);
3357
3365
  }
@@ -3362,6 +3370,7 @@ class ProjectService {
3362
3370
  #lastSeenProject = "";
3363
3371
  #resolvedConfig;
3364
3372
  #seenPrograms = new WeakSet();
3373
+ #seenTestFiles = new Set();
3365
3374
  #service;
3366
3375
  constructor(compiler, resolvedConfig) {
3367
3376
  this.#compiler = compiler;
@@ -3399,15 +3408,6 @@ class ProjectService {
3399
3408
  useInferredProjectPerProjectRoot: true,
3400
3409
  useSingleInferredProject: false,
3401
3410
  });
3402
- switch (this.#resolvedConfig.tsconfig) {
3403
- case "findup":
3404
- break;
3405
- case "ignore":
3406
- this.#service.getConfigFileNameForFile = () => undefined;
3407
- break;
3408
- default:
3409
- this.#service.getConfigFileNameForFile = () => this.#resolvedConfig.tsconfig;
3410
- }
3411
3411
  this.#service.setCompilerOptionsForInferredProjects(this.#getDefaultCompilerOptions());
3412
3412
  }
3413
3413
  closeFile(filePath) {
@@ -3415,7 +3415,6 @@ class ProjectService {
3415
3415
  }
3416
3416
  #getDefaultCompilerOptions() {
3417
3417
  const defaultCompilerOptions = {
3418
- allowImportingTsExtensions: true,
3419
3418
  allowJs: true,
3420
3419
  checkJs: true,
3421
3420
  exactOptionalPropertyTypes: true,
@@ -3426,8 +3425,11 @@ class ProjectService {
3426
3425
  resolveJsonModule: true,
3427
3426
  strict: true,
3428
3427
  target: this.#compiler.ScriptTarget.ESNext,
3429
- verbatimModuleSyntax: true,
3430
3428
  };
3429
+ if (Version.isSatisfiedWith(this.#compiler.version, "5.0")) {
3430
+ defaultCompilerOptions.allowImportingTsExtensions = true;
3431
+ defaultCompilerOptions.verbatimModuleSyntax = true;
3432
+ }
3431
3433
  return defaultCompilerOptions;
3432
3434
  }
3433
3435
  getDefaultProject(filePath) {
@@ -3442,7 +3444,23 @@ class ProjectService {
3442
3444
  const project = this.getDefaultProject(filePath);
3443
3445
  return project?.getLanguageService(true);
3444
3446
  }
3447
+ #isFileIncluded(filePath) {
3448
+ const configSourceFile = this.#compiler.readJsonConfigFile(this.#resolvedConfig.tsconfig, this.#compiler.sys.readFile);
3449
+ const { fileNames } = this.#compiler.parseJsonSourceFileConfigFileContent(configSourceFile, this.#compiler.sys, Path.dirname(this.#resolvedConfig.tsconfig), undefined, this.#resolvedConfig.tsconfig);
3450
+ return fileNames.includes(filePath);
3451
+ }
3445
3452
  openFile(filePath, sourceText, projectRootPath) {
3453
+ switch (this.#resolvedConfig.tsconfig) {
3454
+ case "findup":
3455
+ break;
3456
+ case "ignore":
3457
+ this.#service.getConfigFileNameForFile = () => undefined;
3458
+ break;
3459
+ default:
3460
+ this.#service.getConfigFileNameForFile = this.#isFileIncluded(filePath)
3461
+ ? () => this.#resolvedConfig.tsconfig
3462
+ : () => undefined;
3463
+ }
3446
3464
  const { configFileErrors, configFileName } = this.#service.openClientFile(filePath, sourceText, undefined, projectRootPath);
3447
3465
  if (configFileName !== this.#lastSeenProject) {
3448
3466
  this.#lastSeenProject = configFileName;
@@ -3457,29 +3475,29 @@ class ProjectService {
3457
3475
  { diagnostics: Diagnostic.fromDiagnostics(configFileErrors) },
3458
3476
  ]);
3459
3477
  }
3460
- if (this.#resolvedConfig.checkSourceFiles && !sourceText) {
3478
+ if (this.#resolvedConfig.checkSourceFiles && !this.#seenTestFiles.has(filePath)) {
3479
+ this.#seenTestFiles.add(filePath);
3461
3480
  const languageService = this.getLanguageService(filePath);
3462
3481
  const program = languageService?.getProgram();
3463
3482
  if (!program || this.#seenPrograms.has(program)) {
3464
3483
  return;
3465
3484
  }
3466
3485
  this.#seenPrograms.add(program);
3467
- const filesToCheck = [];
3468
- for (const sourceFile of program.getSourceFiles()) {
3486
+ const sourceFilesToCheck = program.getSourceFiles().filter((sourceFile) => {
3469
3487
  if (program.isSourceFileFromExternalLibrary(sourceFile) || program.isSourceFileDefaultLibrary(sourceFile)) {
3470
- continue;
3488
+ return false;
3471
3489
  }
3472
- if (!Select.isTestFile(sourceFile.fileName, { ...this.#resolvedConfig, pathMatch: [] })) {
3473
- filesToCheck.push(sourceFile);
3490
+ if (Select.isTestFile(sourceFile.fileName, { ...this.#resolvedConfig, pathMatch: [] })) {
3491
+ return false;
3474
3492
  }
3475
- }
3493
+ return true;
3494
+ });
3476
3495
  const diagnostics = [];
3477
- for (const sourceFile of filesToCheck) {
3496
+ for (const sourceFile of sourceFilesToCheck) {
3478
3497
  diagnostics.push(...program.getSyntacticDiagnostics(sourceFile), ...program.getSemanticDiagnostics(sourceFile));
3479
3498
  }
3480
3499
  if (diagnostics.length > 0) {
3481
3500
  EventEmitter.dispatch(["project:error", { diagnostics: Diagnostic.fromDiagnostics(diagnostics) }]);
3482
- return;
3483
3501
  }
3484
3502
  }
3485
3503
  }
@@ -3494,22 +3512,41 @@ var RunMode;
3494
3512
  RunMode[RunMode["Todo"] = 8] = "Todo";
3495
3513
  })(RunMode || (RunMode = {}));
3496
3514
 
3497
- function capitalize(text) {
3498
- return text.replace(/^./, text.charAt(0).toUpperCase());
3499
- }
3500
-
3501
- class ExpectDiagnosticText {
3502
- static argumentCannotBeOfType(argumentNameText, typeText) {
3503
- return `An argument for '${argumentNameText}' cannot be of the '${typeText}' type.`;
3515
+ class EnsureDiagnosticText {
3516
+ static argumentMustBeProvided(argumentNameText) {
3517
+ return `An argument for '${argumentNameText}' must be provided.`;
3504
3518
  }
3505
3519
  static argumentOrTypeArgumentMustBeProvided(argumentNameText, typeArgumentNameText) {
3506
3520
  return `An argument for '${argumentNameText}' or type argument for '${typeArgumentNameText}' must be provided.`;
3507
3521
  }
3522
+ }
3523
+
3524
+ function argumentIsProvided(argumentNameText, node, enclosingNode, onDiagnostics) {
3525
+ if (!node) {
3526
+ const text = EnsureDiagnosticText.argumentMustBeProvided(argumentNameText);
3527
+ const origin = DiagnosticOrigin.fromNode(enclosingNode);
3528
+ onDiagnostics([Diagnostic.error(text, origin)]);
3529
+ return false;
3530
+ }
3531
+ return true;
3532
+ }
3533
+
3534
+ function argumentOrTypeArgumentIsProvided(argumentNameText, typeArgumentNameText, node, enclosingNode, onDiagnostics) {
3535
+ if (!node) {
3536
+ const text = EnsureDiagnosticText.argumentOrTypeArgumentMustBeProvided(argumentNameText, typeArgumentNameText);
3537
+ const origin = DiagnosticOrigin.fromNode(enclosingNode);
3538
+ onDiagnostics([Diagnostic.error(text, origin)]);
3539
+ return false;
3540
+ }
3541
+ return true;
3542
+ }
3543
+
3544
+ class ExpectDiagnosticText {
3508
3545
  static argumentMustBe(argumentNameText, expectedText) {
3509
3546
  return `An argument for '${argumentNameText}' must be ${expectedText}.`;
3510
3547
  }
3511
- static argumentMustBeProvided(argumentNameText) {
3512
- return `An argument for '${argumentNameText}' must be provided.`;
3548
+ static typeArgumentMustBe(argumentNameText, expectedText) {
3549
+ return `A type argument for '${argumentNameText}' must be ${expectedText}.`;
3513
3550
  }
3514
3551
  static isCallable(isExpression, targetText) {
3515
3552
  return `${isExpression ? "Expression" : "Type"} is callable ${targetText}.`;
@@ -3535,12 +3572,12 @@ class ExpectDiagnosticText {
3535
3572
  static cannotBeApplied(targetText) {
3536
3573
  return `The decorator function cannot be applied${targetText}.`;
3537
3574
  }
3538
- static doesNotHaveProperty(typeText, propertyNameText) {
3539
- return `Type '${typeText}' does not have property '${propertyNameText}'.`;
3540
- }
3541
3575
  static hasProperty(typeText, propertyNameText) {
3542
3576
  return `Type '${typeText}' has property '${propertyNameText}'.`;
3543
3577
  }
3578
+ static doesNotHaveProperty(typeText, propertyNameText) {
3579
+ return `Type '${typeText}' does not have property '${propertyNameText}'.`;
3580
+ }
3544
3581
  static didYouMeanToUse(suggestionText) {
3545
3582
  return `Did you mean to use ${suggestionText}?`;
3546
3583
  }
@@ -3553,12 +3590,6 @@ class ExpectDiagnosticText {
3553
3590
  static raisedTypeError(count = 1) {
3554
3591
  return `The raised type error${count === 1 ? "" : "s"}:`;
3555
3592
  }
3556
- static typeArgumentCannotBeOfType(argumentNameText, typeText) {
3557
- return `A type argument for '${argumentNameText}' cannot be of the '${typeText}' type.`;
3558
- }
3559
- static typeArgumentMustBe(argumentNameText, expectedText) {
3560
- return `A type argument for '${argumentNameText}' must be ${expectedText}.`;
3561
- }
3562
3593
  static raisedError(isExpression, count, targetCount) {
3563
3594
  let countText = "a";
3564
3595
  if (count > 1 || targetCount > 1) {
@@ -3602,13 +3633,6 @@ class ExpectDiagnosticText {
3602
3633
  static typesOfPropertyAreNotCompatible(propertyNameText) {
3603
3634
  return `Types of property '${propertyNameText}' are not compatible.`;
3604
3635
  }
3605
- static typeWasRejected(typeText) {
3606
- const optionNameText = `reject${capitalize(typeText)}Type`;
3607
- return [
3608
- `The '${typeText}' type was rejected because the '${optionNameText}' option is enabled.`,
3609
- `If this check is necessary, pass '${typeText}' as the type argument explicitly.`,
3610
- ];
3611
- }
3612
3636
  }
3613
3637
 
3614
3638
  class MatchWorker {
@@ -4317,7 +4341,7 @@ class ToRaiseError {
4317
4341
 
4318
4342
  class ExpectService {
4319
4343
  #compiler;
4320
- #rejectTypes = new Set();
4344
+ #reject;
4321
4345
  #typeChecker;
4322
4346
  toAcceptProps;
4323
4347
  toBe;
@@ -4328,15 +4352,10 @@ class ExpectService {
4328
4352
  toBeConstructableWith;
4329
4353
  toHaveProperty;
4330
4354
  toRaiseError;
4331
- constructor(compiler, typeChecker, resolvedConfig) {
4355
+ constructor(compiler, typeChecker, reject) {
4332
4356
  this.#compiler = compiler;
4357
+ this.#reject = reject;
4333
4358
  this.#typeChecker = typeChecker;
4334
- if (resolvedConfig?.rejectAnyType) {
4335
- this.#rejectTypes.add("any");
4336
- }
4337
- if (resolvedConfig?.rejectNeverType) {
4338
- this.#rejectTypes.add("never");
4339
- }
4340
4359
  this.toAcceptProps = new ToAcceptProps(compiler, typeChecker);
4341
4360
  this.toBe = new ToBe();
4342
4361
  this.toBeApplicable = new ToBeApplicable(compiler);
@@ -4349,13 +4368,15 @@ class ExpectService {
4349
4368
  }
4350
4369
  match(assertion, onDiagnostics) {
4351
4370
  const matcherNameText = assertion.matcherNameNode.name.text;
4352
- if (!assertion.source[0]) {
4353
- this.#onSourceArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics);
4371
+ if (!argumentOrTypeArgumentIsProvided("source", "Source", assertion.source[0], assertion.node.expression, onDiagnostics)) {
4354
4372
  return;
4355
4373
  }
4356
4374
  const matchWorker = new MatchWorker(this.#compiler, this.#typeChecker, assertion);
4357
4375
  if (!(matcherNameText === "toRaiseError" && assertion.isNot === false) &&
4358
- this.#rejectsTypeArguments(matchWorker, onDiagnostics)) {
4376
+ this.#reject.argumentType([
4377
+ ["source", assertion.source[0]],
4378
+ ["target", assertion.target?.[0]],
4379
+ ], onDiagnostics)) {
4359
4380
  return;
4360
4381
  }
4361
4382
  switch (matcherNameText) {
@@ -4363,8 +4384,7 @@ class ExpectService {
4363
4384
  case "toBe":
4364
4385
  case "toBeAssignableTo":
4365
4386
  case "toBeAssignableWith":
4366
- if (!assertion.target?.[0]) {
4367
- this.#onTargetArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics);
4387
+ if (!argumentOrTypeArgumentIsProvided("target", "Target", assertion.target?.[0], assertion.matcherNameNode.name, onDiagnostics)) {
4368
4388
  return;
4369
4389
  }
4370
4390
  return this[matcherNameText].match(matchWorker, assertion.source[0], assertion.target[0], onDiagnostics);
@@ -4375,8 +4395,7 @@ class ExpectService {
4375
4395
  case "toRaiseError":
4376
4396
  return this[matcherNameText].match(matchWorker, assertion.source[0], assertion.target, onDiagnostics);
4377
4397
  case "toHaveProperty":
4378
- if (!assertion.target?.[0]) {
4379
- this.#onTargetArgumentMustBeProvided("key", assertion, onDiagnostics);
4398
+ if (!argumentIsProvided("key", assertion.target?.[0], assertion.matcherNameNode.name, onDiagnostics)) {
4380
4399
  return;
4381
4400
  }
4382
4401
  return this.toHaveProperty.match(matchWorker, assertion.source[0], assertion.target[0], onDiagnostics);
@@ -4390,42 +4409,61 @@ class ExpectService {
4390
4409
  const origin = DiagnosticOrigin.fromNode(assertion.matcherNameNode.name);
4391
4410
  onDiagnostics(Diagnostic.error(text, origin));
4392
4411
  }
4393
- #onSourceArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics) {
4394
- const text = ExpectDiagnosticText.argumentOrTypeArgumentMustBeProvided("source", "Source");
4395
- const origin = DiagnosticOrigin.fromNode(assertion.node.expression);
4396
- onDiagnostics(Diagnostic.error(text, origin));
4412
+ }
4413
+
4414
+ function capitalize(text) {
4415
+ return text.replace(/^./, text.charAt(0).toUpperCase());
4416
+ }
4417
+
4418
+ class RejectDiagnosticText {
4419
+ static argumentCannotBeOfType(argumentNameText, typeText) {
4420
+ return `An argument for '${argumentNameText}' cannot be of the '${typeText}' type.`;
4397
4421
  }
4398
- #onTargetArgumentMustBeProvided(argumentNameText, assertion, onDiagnostics) {
4399
- const text = ExpectDiagnosticText.argumentMustBeProvided(argumentNameText);
4400
- const origin = DiagnosticOrigin.fromNode(assertion.matcherNameNode.name);
4401
- onDiagnostics(Diagnostic.error(text, origin));
4422
+ static typeArgumentCannotBeOfType(argumentNameText, typeText) {
4423
+ return `A type argument for '${argumentNameText}' cannot be of the '${typeText}' type.`;
4402
4424
  }
4403
- #onTargetArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics) {
4404
- const text = ExpectDiagnosticText.argumentOrTypeArgumentMustBeProvided("target", "Target");
4405
- const origin = DiagnosticOrigin.fromNode(assertion.matcherNameNode.name);
4406
- onDiagnostics(Diagnostic.error(text, origin));
4425
+ static typeWasRejected(typeText) {
4426
+ const optionNameText = `reject${capitalize(typeText)}Type`;
4427
+ return [
4428
+ `The '${typeText}' type was rejected because the '${optionNameText}' option is enabled.`,
4429
+ `If this check is necessary, pass '${typeText}' as the type argument explicitly.`,
4430
+ ];
4431
+ }
4432
+ }
4433
+
4434
+ class Reject {
4435
+ #compiler;
4436
+ #rejectedArgumentTypes = new Set();
4437
+ #typeChecker;
4438
+ constructor(compiler, typeChecker, resolvedConfig) {
4439
+ this.#compiler = compiler;
4440
+ this.#typeChecker = typeChecker;
4441
+ if (resolvedConfig?.rejectAnyType) {
4442
+ this.#rejectedArgumentTypes.add("any");
4443
+ }
4444
+ if (resolvedConfig?.rejectNeverType) {
4445
+ this.#rejectedArgumentTypes.add("never");
4446
+ }
4407
4447
  }
4408
- #rejectsTypeArguments(matchWorker, onDiagnostics) {
4409
- for (const rejectedType of this.#rejectTypes) {
4448
+ argumentType(target, onDiagnostics) {
4449
+ for (const rejectedType of this.#rejectedArgumentTypes) {
4410
4450
  const allowedKeyword = this.#compiler.SyntaxKind[`${capitalize(rejectedType)}Keyword`];
4411
- if (matchWorker.assertion.source[0]?.kind === allowedKeyword ||
4412
- matchWorker.assertion.target?.[0]?.kind === allowedKeyword) {
4451
+ if (target.some(([, node]) => node?.kind === allowedKeyword)) {
4413
4452
  continue;
4414
4453
  }
4415
- for (const argumentName of ["source", "target"]) {
4416
- const argumentNode = matchWorker.assertion[argumentName]?.[0];
4417
- if (!argumentNode) {
4454
+ for (const [name, node] of target) {
4455
+ if (!node) {
4418
4456
  continue;
4419
4457
  }
4420
- if (matchWorker.getType(argumentNode).flags & this.#compiler.TypeFlags[capitalize(rejectedType)]) {
4458
+ if (this.#typeChecker.getTypeAtLocation(node).flags & this.#compiler.TypeFlags[capitalize(rejectedType)]) {
4421
4459
  const text = [
4422
- nodeBelongsToArgumentList(this.#compiler, argumentNode)
4423
- ? ExpectDiagnosticText.argumentCannotBeOfType(argumentName, rejectedType)
4424
- : ExpectDiagnosticText.typeArgumentCannotBeOfType(capitalize(argumentName), rejectedType),
4425
- ...ExpectDiagnosticText.typeWasRejected(rejectedType),
4460
+ nodeBelongsToArgumentList(this.#compiler, node)
4461
+ ? RejectDiagnosticText.argumentCannotBeOfType(name, rejectedType)
4462
+ : RejectDiagnosticText.typeArgumentCannotBeOfType(capitalize(name), rejectedType),
4463
+ ...RejectDiagnosticText.typeWasRejected(rejectedType),
4426
4464
  ];
4427
- const origin = DiagnosticOrigin.fromNode(argumentNode);
4428
- onDiagnostics(Diagnostic.error(text, origin));
4465
+ const origin = DiagnosticOrigin.fromNode(node);
4466
+ onDiagnostics([Diagnostic.error(text, origin)]);
4429
4467
  return true;
4430
4468
  }
4431
4469
  }
@@ -4434,20 +4472,78 @@ class ExpectService {
4434
4472
  }
4435
4473
  }
4436
4474
 
4475
+ class WhenDiagnosticText {
4476
+ static actionIsNotSupported(actionNameText) {
4477
+ return `The '.${actionNameText}()' action is not supported.`;
4478
+ }
4479
+ }
4480
+
4481
+ class WhenService {
4482
+ #onDiagnostics;
4483
+ #reject;
4484
+ constructor(reject, onDiagnostics) {
4485
+ this.#reject = reject;
4486
+ this.#onDiagnostics = onDiagnostics;
4487
+ }
4488
+ action(when) {
4489
+ if (!argumentIsProvided("target", when.target[0], when.node.expression, this.#onDiagnostics) ||
4490
+ this.#reject.argumentType([["target", when.target[0]]], this.#onDiagnostics)) {
4491
+ return;
4492
+ }
4493
+ const actionNameText = when.actionNameNode.name.getText();
4494
+ switch (actionNameText) {
4495
+ case "isCalledWith":
4496
+ break;
4497
+ default:
4498
+ this.#onActionIsNotSupported(actionNameText, when, this.#onDiagnostics);
4499
+ return;
4500
+ }
4501
+ if (when.abilityDiagnostics != null && when.abilityDiagnostics.size > 0) {
4502
+ const diagnostics = [];
4503
+ for (const diagnostic of when.abilityDiagnostics) {
4504
+ if (isDiagnosticWithLocation(diagnostic)) {
4505
+ const text = getDiagnosticMessageText(diagnostic);
4506
+ let origin;
4507
+ if (isDiagnosticWithLocation(diagnostic) && diagnosticBelongsToNode(diagnostic, when.node)) {
4508
+ origin = DiagnosticOrigin.fromNodes(when.target);
4509
+ }
4510
+ else {
4511
+ origin = new DiagnosticOrigin(diagnostic.start, getTextSpanEnd(diagnostic), when.node.getSourceFile());
4512
+ }
4513
+ let related;
4514
+ if (diagnostic.relatedInformation != null) {
4515
+ related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation);
4516
+ }
4517
+ diagnostics.push(Diagnostic.error(text, origin).add({ related }));
4518
+ }
4519
+ }
4520
+ this.#onDiagnostics(diagnostics);
4521
+ }
4522
+ }
4523
+ #onActionIsNotSupported(actionNameText, when, onDiagnostics) {
4524
+ const text = WhenDiagnosticText.actionIsNotSupported(actionNameText);
4525
+ const origin = DiagnosticOrigin.fromNode(when.actionNameNode.name);
4526
+ onDiagnostics([Diagnostic.error(text, origin)]);
4527
+ }
4528
+ }
4529
+
4437
4530
  class TestTreeWalker {
4438
4531
  #cancellationToken;
4439
4532
  #expectService;
4440
4533
  #hasOnly;
4534
+ #onTaskDiagnostics;
4441
4535
  #position;
4442
4536
  #resolvedConfig;
4443
- #taskResult;
4444
- constructor(compiler, typeChecker, resolvedConfig, options) {
4537
+ #whenService;
4538
+ constructor(compiler, typeChecker, resolvedConfig, onTaskDiagnostics, options) {
4445
4539
  this.#resolvedConfig = resolvedConfig;
4540
+ this.#onTaskDiagnostics = onTaskDiagnostics;
4446
4541
  this.#cancellationToken = options.cancellationToken;
4447
4542
  this.#hasOnly = options.hasOnly || resolvedConfig.only != null || options.position != null;
4448
4543
  this.#position = options.position;
4449
- this.#taskResult = options.taskResult;
4450
- this.#expectService = new ExpectService(compiler, typeChecker, this.#resolvedConfig);
4544
+ const reject = new Reject(compiler, typeChecker, resolvedConfig);
4545
+ this.#expectService = new ExpectService(compiler, typeChecker, reject);
4546
+ this.#whenService = new WhenService(reject, onTaskDiagnostics);
4451
4547
  }
4452
4548
  #resolveRunMode(mode, testNode) {
4453
4549
  if (testNode.flags & TestTreeNodeFlags.Fail) {
@@ -4472,28 +4568,23 @@ class TestTreeWalker {
4472
4568
  }
4473
4569
  return mode;
4474
4570
  }
4475
- visit(testNodes, runMode, parentResult) {
4476
- for (const testNode of testNodes) {
4571
+ visit(nodes, runMode, parentResult) {
4572
+ for (const node of nodes) {
4477
4573
  if (this.#cancellationToken?.isCancellationRequested) {
4478
4574
  break;
4479
4575
  }
4480
- const validationError = testNode.validate();
4481
- if (validationError.length > 0) {
4482
- EventEmitter.dispatch(["task:error", { diagnostics: validationError, result: this.#taskResult }]);
4483
- break;
4484
- }
4485
- switch (testNode.brand) {
4576
+ switch (node.brand) {
4486
4577
  case TestTreeNodeBrand.Describe:
4487
- this.#visitDescribe(testNode, runMode, parentResult);
4578
+ this.#visitDescribe(node, runMode, parentResult);
4488
4579
  break;
4489
4580
  case TestTreeNodeBrand.Test:
4490
- this.#visitTest(testNode, runMode, parentResult);
4581
+ this.#visitTest(node, runMode, parentResult);
4491
4582
  break;
4492
4583
  case TestTreeNodeBrand.Expect:
4493
- this.#visitAssertion(testNode, runMode, parentResult);
4584
+ this.#visitAssertion(node, runMode, parentResult);
4494
4585
  break;
4495
4586
  case TestTreeNodeBrand.When:
4496
- this.#visitWhen(testNode, runMode, parentResult);
4587
+ this.#visitWhen(node);
4497
4588
  break;
4498
4589
  }
4499
4590
  }
@@ -4544,13 +4635,7 @@ class TestTreeWalker {
4544
4635
  runMode = this.#resolveRunMode(runMode, describe);
4545
4636
  if (!(runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only)) || runMode & RunMode.Todo) &&
4546
4637
  describe.diagnostics.size > 0) {
4547
- EventEmitter.dispatch([
4548
- "task:error",
4549
- {
4550
- diagnostics: Diagnostic.fromDiagnostics([...describe.diagnostics]),
4551
- result: this.#taskResult,
4552
- },
4553
- ]);
4638
+ this.#onTaskDiagnostics(Diagnostic.fromDiagnostics([...describe.diagnostics]));
4554
4639
  }
4555
4640
  else {
4556
4641
  this.visit(describe.children, runMode, describeResult);
@@ -4587,36 +4672,14 @@ class TestTreeWalker {
4587
4672
  EventEmitter.dispatch(["test:pass", { result: testResult }]);
4588
4673
  }
4589
4674
  }
4590
- #visitWhen(when, _runMode, _parentResult) {
4591
- if (when.abilityDiagnostics != null && when.abilityDiagnostics.size > 0) {
4592
- const diagnostics = [];
4593
- for (const diagnostic of when.abilityDiagnostics) {
4594
- if (isDiagnosticWithLocation(diagnostic)) {
4595
- const text = getDiagnosticMessageText(diagnostic);
4596
- let origin;
4597
- if (isDiagnosticWithLocation(diagnostic) && diagnosticBelongsToNode(diagnostic, when.node)) {
4598
- origin = DiagnosticOrigin.fromNodes(when.target);
4599
- }
4600
- else {
4601
- origin = new DiagnosticOrigin(diagnostic.start, getTextSpanEnd(diagnostic), when.node.getSourceFile());
4602
- }
4603
- let related;
4604
- if (diagnostic.relatedInformation != null) {
4605
- related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation);
4606
- }
4607
- diagnostics.push(Diagnostic.error(text, origin).add({ related }));
4608
- }
4609
- }
4610
- EventEmitter.dispatch(["task:error", { diagnostics, result: this.#taskResult }]);
4611
- return;
4612
- }
4675
+ #visitWhen(when) {
4676
+ this.#whenService.action(when);
4613
4677
  }
4614
4678
  }
4615
4679
 
4616
4680
  class TaskRunner {
4617
4681
  #collectService;
4618
4682
  #compiler;
4619
- #eventEmitter = new EventEmitter();
4620
4683
  #resolvedConfig;
4621
4684
  #projectService;
4622
4685
  constructor(compiler, resolvedConfig) {
@@ -4625,6 +4688,9 @@ class TaskRunner {
4625
4688
  this.#projectService = new ProjectService(compiler, this.#resolvedConfig);
4626
4689
  this.#collectService = new CollectService(compiler, this.#projectService, this.#resolvedConfig);
4627
4690
  }
4691
+ #onDiagnostics(diagnostics, result) {
4692
+ EventEmitter.dispatch(["task:error", { diagnostics, result }]);
4693
+ }
4628
4694
  async run(task, cancellationToken) {
4629
4695
  if (cancellationToken.isCancellationRequested) {
4630
4696
  return;
@@ -4638,19 +4704,13 @@ class TaskRunner {
4638
4704
  }
4639
4705
  async #run(task, taskResult, cancellationToken) {
4640
4706
  if (!existsSync(task.filePath)) {
4641
- EventEmitter.dispatch([
4642
- "task:error",
4643
- { diagnostics: [Diagnostic.error(`Test file '${task.filePath}' does not exist.`)], result: taskResult },
4644
- ]);
4707
+ this.#onDiagnostics([Diagnostic.error(`Test file '${task.filePath}' does not exist.`)], taskResult);
4645
4708
  return;
4646
4709
  }
4647
4710
  let languageService = this.#projectService.getLanguageService(task.filePath);
4648
4711
  const syntacticDiagnostics = languageService?.getSyntacticDiagnostics(task.filePath);
4649
4712
  if (syntacticDiagnostics != null && syntacticDiagnostics.length > 0) {
4650
- EventEmitter.dispatch([
4651
- "task:error",
4652
- { diagnostics: Diagnostic.fromDiagnostics(syntacticDiagnostics), result: taskResult },
4653
- ]);
4713
+ this.#onDiagnostics(Diagnostic.fromDiagnostics(syntacticDiagnostics), taskResult);
4654
4714
  return;
4655
4715
  }
4656
4716
  let semanticDiagnostics = languageService?.getSemanticDiagnostics(task.filePath);
@@ -4658,21 +4718,20 @@ class TaskRunner {
4658
4718
  let sourceFile = program?.getSourceFile(task.filePath);
4659
4719
  if (sourceFile?.text.startsWith("// @tstyche-template")) {
4660
4720
  if (semanticDiagnostics != null && semanticDiagnostics.length > 0) {
4661
- EventEmitter.dispatch([
4662
- "task:error",
4663
- { diagnostics: Diagnostic.fromDiagnostics(semanticDiagnostics), result: taskResult },
4664
- ]);
4721
+ this.#onDiagnostics(Diagnostic.fromDiagnostics(semanticDiagnostics), taskResult);
4722
+ return;
4723
+ }
4724
+ const moduleSpecifier = pathToFileURL(task.filePath).toString();
4725
+ const testText = (await import(moduleSpecifier))?.default;
4726
+ if (typeof testText !== "string") {
4727
+ this.#onDiagnostics([Diagnostic.error("A template test file must export a string.")], taskResult);
4665
4728
  return;
4666
4729
  }
4667
- const text = (await import(task.filePath)).default;
4668
- this.#projectService.openFile(task.filePath, text, this.#resolvedConfig.rootPath);
4730
+ this.#projectService.openFile(task.filePath, testText, this.#resolvedConfig.rootPath);
4669
4731
  languageService = this.#projectService.getLanguageService(task.filePath);
4670
4732
  const syntacticDiagnostics = languageService?.getSyntacticDiagnostics(task.filePath);
4671
4733
  if (syntacticDiagnostics != null && syntacticDiagnostics.length > 0) {
4672
- EventEmitter.dispatch([
4673
- "task:error",
4674
- { diagnostics: Diagnostic.fromDiagnostics(syntacticDiagnostics), result: taskResult },
4675
- ]);
4734
+ this.#onDiagnostics(Diagnostic.fromDiagnostics(syntacticDiagnostics), taskResult);
4676
4735
  return;
4677
4736
  }
4678
4737
  semanticDiagnostics = languageService?.getSemanticDiagnostics(task.filePath);
@@ -4682,24 +4741,17 @@ class TaskRunner {
4682
4741
  if (!sourceFile) {
4683
4742
  return;
4684
4743
  }
4685
- const cancellationHandler = new CancellationHandler(cancellationToken, CancellationReason.CollectError);
4686
- this.#eventEmitter.addHandler(cancellationHandler);
4687
4744
  const testTree = this.#collectService.createTestTree(sourceFile, semanticDiagnostics);
4688
- this.#eventEmitter.removeHandler(cancellationHandler);
4689
- if (cancellationToken.isCancellationRequested) {
4690
- return;
4691
- }
4692
4745
  if (testTree.diagnostics.size > 0) {
4693
- EventEmitter.dispatch([
4694
- "task:error",
4695
- { diagnostics: Diagnostic.fromDiagnostics([...testTree.diagnostics]), result: taskResult },
4696
- ]);
4746
+ this.#onDiagnostics(Diagnostic.fromDiagnostics([...testTree.diagnostics]), taskResult);
4697
4747
  return;
4698
4748
  }
4699
4749
  const typeChecker = program?.getTypeChecker();
4700
- const testTreeWalker = new TestTreeWalker(this.#compiler, typeChecker, this.#resolvedConfig, {
4750
+ const onTaskDiagnostics = (diagnostics) => {
4751
+ this.#onDiagnostics(diagnostics, taskResult);
4752
+ };
4753
+ const testTreeWalker = new TestTreeWalker(this.#compiler, typeChecker, this.#resolvedConfig, onTaskDiagnostics, {
4701
4754
  cancellationToken,
4702
- taskResult,
4703
4755
  hasOnly: testTree.hasOnly,
4704
4756
  position: task.position,
4705
4757
  });
@@ -4710,7 +4762,7 @@ class TaskRunner {
4710
4762
  class Runner {
4711
4763
  #eventEmitter = new EventEmitter();
4712
4764
  #resolvedConfig;
4713
- static version = "4.0.0-beta.7";
4765
+ static version = "4.0.0-beta.9";
4714
4766
  constructor(resolvedConfig) {
4715
4767
  this.#resolvedConfig = resolvedConfig;
4716
4768
  }
@@ -4910,4 +4962,4 @@ class Cli {
4910
4962
  }
4911
4963
  }
4912
4964
 
4913
- export { AssertionNode, 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, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
4965
+ export { AssertionNode, 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, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "4.0.0-beta.7",
3
+ "version": "4.0.0-beta.9",
4
4
  "description": "The Essential Type Testing Tool.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -62,21 +62,21 @@
62
62
  "devDependencies": {
63
63
  "@biomejs/biome": "1.9.4",
64
64
  "@rollup/plugin-typescript": "12.1.2",
65
- "@types/node": "22.15.3",
66
- "@types/react": "19.1.2",
65
+ "@types/node": "22.15.15",
66
+ "@types/react": "19.1.3",
67
67
  "ajv": "8.17.1",
68
- "cspell": "8.19.4",
68
+ "cspell": "9.0.0",
69
69
  "magic-string": "0.30.17",
70
70
  "monocart-coverage-reports": "2.12.4",
71
71
  "pretty-ansi": "3.0.0",
72
- "rollup": "4.40.1",
72
+ "rollup": "4.40.2",
73
73
  "rollup-plugin-dts": "6.2.1",
74
74
  "ts-blank-space": "0.6.1",
75
75
  "tslib": "2.8.1",
76
76
  "typescript": "5.8.3"
77
77
  },
78
78
  "peerDependencies": {
79
- "typescript": "5.x"
79
+ "typescript": ">=4.7"
80
80
  },
81
81
  "peerDependenciesMeta": {
82
82
  "typescript": {