tstyche 1.0.0-beta.9 → 1.0.0-rc.1

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.
package/build/tstyche.js CHANGED
@@ -1,3 +1,4 @@
1
+ import process from 'node:process';
1
2
  import { fileURLToPath, pathToFileURL } from 'node:url';
2
3
  import { createRequire } from 'node:module';
3
4
  import os from 'node:os';
@@ -24,9 +25,6 @@ class EventEmitter {
24
25
  }
25
26
 
26
27
  class Path {
27
- static basename(filePath) {
28
- return Path.normalizeSlashes(path.basename(filePath));
29
- }
30
28
  static dirname(filePath) {
31
29
  return Path.normalizeSlashes(path.dirname(filePath));
32
30
  }
@@ -52,46 +50,41 @@ class Path {
52
50
  }
53
51
 
54
52
  class Environment {
55
- static #isTypeScriptInstalled = Environment.#resolveIsTypeScriptInstalled();
56
53
  static #noColor = Environment.#resolveNoColor();
54
+ static #noInteractive = Environment.#resolveNoInteractive();
57
55
  static #storePath = Environment.#resolveStorePath();
58
56
  static #timeout = Environment.#resolveTimeout();
59
- static get isTypeScriptInstalled() {
60
- return Environment.#isTypeScriptInstalled;
61
- }
57
+ static #typescriptPath = Environment.#resolveTypeScriptPath();
62
58
  static get noColor() {
63
59
  return Environment.#noColor;
64
60
  }
61
+ static get noInteractive() {
62
+ return Environment.#noInteractive;
63
+ }
65
64
  static get storePath() {
66
65
  return Environment.#storePath;
67
66
  }
68
67
  static get timeout() {
69
68
  return Environment.#timeout;
70
69
  }
71
- static #parseBoolean(value) {
72
- if (value != null) {
73
- return ["1", "on", "t", "true", "y", "yes"].includes(value.toLowerCase());
74
- }
75
- return false;
76
- }
77
- static #resolveIsTypeScriptInstalled() {
78
- try {
79
- createRequire(import.meta.url).resolve("typescript");
80
- return true;
81
- }
82
- catch {
83
- return false;
84
- }
70
+ static get typescriptPath() {
71
+ return Environment.#typescriptPath;
85
72
  }
86
73
  static #resolveNoColor() {
87
74
  if (process.env["TSTYCHE_NO_COLOR"] != null) {
88
- return Environment.#parseBoolean(process.env["TSTYCHE_NO_COLOR"]);
75
+ return process.env["TSTYCHE_NO_COLOR"] !== "";
89
76
  }
90
- if (process.env["NO_COLOR"] != null && process.env["NO_COLOR"] !== "") {
91
- return true;
77
+ if (process.env["NO_COLOR"] != null) {
78
+ return process.env["NO_COLOR"] !== "";
92
79
  }
93
80
  return false;
94
81
  }
82
+ static #resolveNoInteractive() {
83
+ if (process.env["TSTYCHE_NO_INTERACTIVE"] != null) {
84
+ return process.env["TSTYCHE_NO_INTERACTIVE"] !== "";
85
+ }
86
+ return !process.stdout.isTTY;
87
+ }
95
88
  static #resolveStorePath() {
96
89
  if (process.env["TSTYCHE_STORE_PATH"] != null) {
97
90
  return Path.resolve(process.env["TSTYCHE_STORE_PATH"]);
@@ -113,6 +106,19 @@ class Environment {
113
106
  }
114
107
  return 30;
115
108
  }
109
+ static #resolveTypeScriptPath() {
110
+ let moduleId = "typescript";
111
+ if (process.env["TSTYCHE_TYPESCRIPT_PATH"] != null) {
112
+ moduleId = process.env["TSTYCHE_TYPESCRIPT_PATH"];
113
+ }
114
+ let resolvedPath;
115
+ try {
116
+ resolvedPath = createRequire(import.meta.url).resolve(moduleId);
117
+ }
118
+ catch {
119
+ }
120
+ return resolvedPath;
121
+ }
116
122
  }
117
123
 
118
124
  var Color;
@@ -128,9 +134,11 @@ var Color;
128
134
  })(Color || (Color = {}));
129
135
 
130
136
  class Scribbler {
137
+ #newLine;
131
138
  #noColor;
132
139
  constructor(options) {
133
- this.#noColor = options?.noColors ?? false;
140
+ this.#newLine = options?.newLine ?? "\n";
141
+ this.#noColor = options?.noColor ?? false;
134
142
  }
135
143
  static createElement(type, props, ...children) {
136
144
  return {
@@ -165,8 +173,8 @@ class Scribbler {
165
173
  return this.#escapeSequence(flags);
166
174
  }
167
175
  }
168
- if (element.type === "newline") {
169
- return "\r\n";
176
+ if (element.type === "newLine") {
177
+ return this.#newLine;
170
178
  }
171
179
  if (element.type === "text") {
172
180
  const indentLevel = typeof element.props?.["indent"] === "number" ? element.props["indent"] : 0;
@@ -233,7 +241,7 @@ class Line {
233
241
  render() {
234
242
  return (Scribbler.createElement("text", null,
235
243
  Scribbler.createElement(Text, { color: this.props.color, indent: this.props.indent }, this.props.children),
236
- Scribbler.createElement("newline", null)));
244
+ Scribbler.createElement("newLine", null)));
237
245
  }
238
246
  }
239
247
 
@@ -246,20 +254,11 @@ class Logger {
246
254
  this.#noColor = options?.noColor ?? Environment.noColor;
247
255
  this.#stderr = options?.stderr ?? process.stderr;
248
256
  this.#stdout = options?.stdout ?? process.stdout;
249
- this.#scribbler = new Scribbler({ noColors: this.#noColor });
257
+ this.#scribbler = new Scribbler({ noColor: this.#noColor });
250
258
  }
251
259
  eraseLastLine() {
252
- if (!this.isInteractive()) {
253
- return;
254
- }
255
260
  this.#stdout.write("\u001B[1A\u001B[0K");
256
261
  }
257
- isInteractive() {
258
- if ("isTTY" in this.#stdout && typeof this.#stdout.isTTY === "boolean") {
259
- return this.#stdout.isTTY;
260
- }
261
- return false;
262
- }
263
262
  #write(stream, body) {
264
263
  const elements = Array.isArray(body) ? body : [body];
265
264
  for (const element of elements) {
@@ -346,7 +345,7 @@ class CodeSpanText {
346
345
  }
347
346
  }
348
347
  const breadcrumbs = this.props.breadcrumbs?.flatMap((ancestor) => [
349
- Scribbler.createElement(Text, { color: "90" }, " \u276D "),
348
+ Scribbler.createElement(Text, { color: "90" }, " "),
350
349
  Scribbler.createElement(Text, null, ancestor),
351
350
  ]);
352
351
  const location = (Scribbler.createElement(Line, null,
@@ -373,9 +372,11 @@ class DiagnosticText {
373
372
  this.props = props;
374
373
  }
375
374
  render() {
376
- const code = typeof this.props.diagnostic.code === "string" ? (Scribbler.createElement(Text, { color: "90" },
377
- " ",
378
- this.props.diagnostic.code)) : undefined;
375
+ const code = typeof this.props.diagnostic.code === "string"
376
+ ? Scribbler.createElement(Text, { color: "90" },
377
+ " ",
378
+ this.props.diagnostic.code)
379
+ : undefined;
379
380
  const text = Array.isArray(this.props.diagnostic.text) ? this.props.diagnostic.text : [this.props.diagnostic.text];
380
381
  const message = text.map((text, index) => (Scribbler.createElement(Text, null,
381
382
  index === 1 ? Scribbler.createElement(Line, null) : undefined,
@@ -383,9 +384,11 @@ class DiagnosticText {
383
384
  text,
384
385
  code))));
385
386
  const related = this.props.diagnostic.related?.map((relatedDiagnostic) => (Scribbler.createElement(DiagnosticText, { diagnostic: relatedDiagnostic })));
386
- const codeSpan = this.props.diagnostic.origin ? (Scribbler.createElement(Text, null,
387
- Scribbler.createElement(Line, null),
388
- Scribbler.createElement(CodeSpanText, { ...this.props.diagnostic.origin }))) : undefined;
387
+ const codeSpan = this.props.diagnostic.origin
388
+ ? (Scribbler.createElement(Text, null,
389
+ Scribbler.createElement(Line, null),
390
+ Scribbler.createElement(CodeSpanText, { ...this.props.diagnostic.origin })))
391
+ : undefined;
389
392
  return (Scribbler.createElement(Text, null,
390
393
  message,
391
394
  codeSpan,
@@ -482,7 +485,7 @@ function formattedText(input) {
482
485
  const usageExamples = [
483
486
  ["tstyche", "Run all tests."],
484
487
  ["tstyche path/to/first.test.ts", "Only run the test files with matching path."],
485
- ["tstyche --target 4.7,5.3.2,current", "Test on all specified versions of TypeScript."],
488
+ ["tstyche --target 4.9,5.3.2,current", "Test on all specified versions of TypeScript."],
486
489
  ];
487
490
  class HintText {
488
491
  props;
@@ -624,26 +627,34 @@ class CountText {
624
627
  }
625
628
  render() {
626
629
  return (Scribbler.createElement(Text, null,
627
- this.props.failed > 0 ? (Scribbler.createElement(Text, null,
628
- Scribbler.createElement(Text, { color: "31" },
629
- String(this.props.failed),
630
- " failed"),
631
- Scribbler.createElement(Text, null, ", "))) : undefined,
632
- this.props.skipped > 0 ? (Scribbler.createElement(Text, null,
633
- Scribbler.createElement(Text, { color: "33" },
634
- String(this.props.skipped),
635
- " skipped"),
636
- Scribbler.createElement(Text, null, ", "))) : undefined,
637
- this.props.todo > 0 ? (Scribbler.createElement(Text, null,
638
- Scribbler.createElement(Text, { color: "35" },
639
- String(this.props.todo),
640
- " todo"),
641
- Scribbler.createElement(Text, null, ", "))) : undefined,
642
- this.props.passed > 0 ? (Scribbler.createElement(Text, null,
643
- Scribbler.createElement(Text, { color: "32" },
644
- String(this.props.passed),
645
- " passed"),
646
- Scribbler.createElement(Text, null, ", "))) : undefined,
630
+ this.props.failed > 0
631
+ ? (Scribbler.createElement(Text, null,
632
+ Scribbler.createElement(Text, { color: "31" },
633
+ String(this.props.failed),
634
+ " failed"),
635
+ Scribbler.createElement(Text, null, ", ")))
636
+ : undefined,
637
+ this.props.skipped > 0
638
+ ? (Scribbler.createElement(Text, null,
639
+ Scribbler.createElement(Text, { color: "33" },
640
+ String(this.props.skipped),
641
+ " skipped"),
642
+ Scribbler.createElement(Text, null, ", ")))
643
+ : undefined,
644
+ this.props.todo > 0
645
+ ? (Scribbler.createElement(Text, null,
646
+ Scribbler.createElement(Text, { color: "35" },
647
+ String(this.props.todo),
648
+ " todo"),
649
+ Scribbler.createElement(Text, null, ", ")))
650
+ : undefined,
651
+ this.props.passed > 0
652
+ ? (Scribbler.createElement(Text, null,
653
+ Scribbler.createElement(Text, { color: "32" },
654
+ String(this.props.passed),
655
+ " passed"),
656
+ Scribbler.createElement(Text, null, ", ")))
657
+ : undefined,
647
658
  Scribbler.createElement(Text, null,
648
659
  String(this.props.total),
649
660
  Scribbler.createElement(Text, null, " total"))));
@@ -815,92 +826,6 @@ class SummaryReporter extends Reporter {
815
826
  }
816
827
  }
817
828
 
818
- class Diagnostic {
819
- text;
820
- category;
821
- origin;
822
- code;
823
- related;
824
- constructor(text, category, origin) {
825
- this.text = text;
826
- this.category = category;
827
- this.origin = origin;
828
- }
829
- add(options) {
830
- if (options.code != null) {
831
- this.code = options.code;
832
- }
833
- if (options.origin != null) {
834
- this.origin = options.origin;
835
- }
836
- if (options.related != null) {
837
- this.related = options.related;
838
- }
839
- return this;
840
- }
841
- static error(text, origin) {
842
- return new Diagnostic(text, "error", origin);
843
- }
844
- static fromDiagnostics(diagnostics, compiler) {
845
- return diagnostics.map((diagnostic) => {
846
- let category;
847
- switch (diagnostic.category) {
848
- case compiler.DiagnosticCategory.Error:
849
- category = "error";
850
- break;
851
- default:
852
- category = "warning";
853
- }
854
- const code = `ts(${diagnostic.code})`;
855
- const text = compiler.flattenDiagnosticMessageText(diagnostic.messageText, "\r\n");
856
- if (Diagnostic.isTsDiagnosticWithLocation(diagnostic)) {
857
- const origin = {
858
- end: diagnostic.start + diagnostic.length,
859
- file: diagnostic.file,
860
- start: diagnostic.start,
861
- };
862
- return new Diagnostic(text, category, origin).add({ code });
863
- }
864
- return new Diagnostic(text, category).add({ code });
865
- });
866
- }
867
- static fromError(text, error) {
868
- const messageText = Array.isArray(text) ? text : [text];
869
- if (error instanceof Error) {
870
- if (error.cause != null) {
871
- messageText.push(this.#normalizeMessage(String(error.cause)));
872
- }
873
- messageText.push(this.#normalizeMessage(String(error.message)));
874
- if (error.stack != null) {
875
- const stackLines = error.stack
876
- .split("\n")
877
- .slice(1)
878
- .map((line) => line.trimStart());
879
- messageText.push(...stackLines);
880
- }
881
- }
882
- return Diagnostic.error(messageText);
883
- }
884
- static isTsDiagnosticWithLocation(diagnostic) {
885
- return diagnostic.file != null && diagnostic.start != null && diagnostic.length != null;
886
- }
887
- static #normalizeMessage(text) {
888
- if (text.endsWith(".")) {
889
- return text;
890
- }
891
- return `${text}.`;
892
- }
893
- static warning(text, origin) {
894
- return new Diagnostic(text, "warning", origin);
895
- }
896
- }
897
-
898
- var DiagnosticCategory;
899
- (function (DiagnosticCategory) {
900
- DiagnosticCategory["Error"] = "error";
901
- DiagnosticCategory["Warning"] = "warning";
902
- })(DiagnosticCategory || (DiagnosticCategory = {}));
903
-
904
829
  class FileViewService {
905
830
  #indent = 0;
906
831
  #lines = [];
@@ -967,19 +892,13 @@ class ThoroughReporter extends Reporter {
967
892
  this.#currentProjectConfigFilePath = undefined;
968
893
  break;
969
894
  case "project:info":
970
- if (this.#currentCompilerVersion !== payload.compilerVersion ||
971
- this.#currentProjectConfigFilePath !== payload.projectConfigFilePath) {
895
+ if (this.#currentCompilerVersion !== payload.compilerVersion
896
+ || this.#currentProjectConfigFilePath !== payload.projectConfigFilePath) {
972
897
  this.logger.writeMessage(usesCompilerStepText(payload.compilerVersion, payload.projectConfigFilePath, {
973
- prependEmptyLine: this.#currentCompilerVersion != null && !this.#hasReportedAdds && !this.#hasReportedError,
898
+ prependEmptyLine: this.#currentCompilerVersion != null && !this.#hasReportedAdds
899
+ && !this.#hasReportedError,
974
900
  }));
975
901
  this.#hasReportedAdds = false;
976
- if (payload.projectConfigFilePath == null) {
977
- const text = [
978
- "The default compiler options are used for the following tests files.",
979
- "Make sure that 'tsconfig.json' exists and the test files are included in the program.",
980
- ];
981
- this.logger.writeWarning(diagnosticText(Diagnostic.warning(text)));
982
- }
983
902
  this.#currentCompilerVersion = payload.compilerVersion;
984
903
  this.#currentProjectConfigFilePath = payload.projectConfigFilePath;
985
904
  }
@@ -990,7 +909,7 @@ class ThoroughReporter extends Reporter {
990
909
  }
991
910
  break;
992
911
  case "file:start":
993
- if (this.logger.isInteractive()) {
912
+ if (!Environment.noInteractive) {
994
913
  this.logger.writeMessage(fileStatusText(payload.result.status, payload.result.testFile));
995
914
  }
996
915
  this.#fileCount--;
@@ -1002,7 +921,9 @@ class ThoroughReporter extends Reporter {
1002
921
  }
1003
922
  break;
1004
923
  case "file:end":
1005
- this.logger.eraseLastLine();
924
+ if (!Environment.noInteractive) {
925
+ this.logger.eraseLastLine();
926
+ }
1006
927
  this.logger.writeMessage(fileStatusText(payload.result.status, payload.result.testFile));
1007
928
  this.logger.writeMessage(this.#fileView.getViewText({ appendEmptyLine: this.#isLastFile }));
1008
929
  if (this.#fileView.hasErrors) {
@@ -1204,9 +1125,9 @@ class ResultManager {
1204
1125
  this.#fileResult.diagnostics.push(...payload.diagnostics);
1205
1126
  break;
1206
1127
  case "file:end":
1207
- if (this.#fileResult.status === "failed" ||
1208
- this.#fileResult.expectCount.failed > 0 ||
1209
- this.#fileResult.testCount.failed > 0) {
1128
+ if (this.#fileResult.status === "failed"
1129
+ || this.#fileResult.expectCount.failed > 0
1130
+ || this.#fileResult.testCount.failed > 0) {
1210
1131
  this.#result.fileCount.failed++;
1211
1132
  this.#targetResult.status = "failed";
1212
1133
  this.#fileResult.status = "failed";
@@ -1368,6 +1289,85 @@ class TestResult {
1368
1289
  }
1369
1290
  }
1370
1291
 
1292
+ class Diagnostic {
1293
+ text;
1294
+ category;
1295
+ origin;
1296
+ code;
1297
+ related;
1298
+ constructor(text, category, origin) {
1299
+ this.text = text;
1300
+ this.category = category;
1301
+ this.origin = origin;
1302
+ }
1303
+ add(options) {
1304
+ if (options.code != null) {
1305
+ this.code = options.code;
1306
+ }
1307
+ if (options.origin != null) {
1308
+ this.origin = options.origin;
1309
+ }
1310
+ if (options.related != null) {
1311
+ this.related = options.related;
1312
+ }
1313
+ return this;
1314
+ }
1315
+ static error(text, origin) {
1316
+ return new Diagnostic(text, "error", origin);
1317
+ }
1318
+ static fromDiagnostics(diagnostics, compiler) {
1319
+ return diagnostics.map((diagnostic) => {
1320
+ const category = "error";
1321
+ const code = `ts(${diagnostic.code})`;
1322
+ let origin;
1323
+ const text = compiler.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
1324
+ if (Diagnostic.isTsDiagnosticWithLocation(diagnostic)) {
1325
+ origin = {
1326
+ end: diagnostic.start + diagnostic.length,
1327
+ file: diagnostic.file,
1328
+ start: diagnostic.start,
1329
+ };
1330
+ }
1331
+ return new Diagnostic(text, category, origin).add({ code });
1332
+ });
1333
+ }
1334
+ static fromError(text, error) {
1335
+ const messageText = Array.isArray(text) ? text : [text];
1336
+ if (error instanceof Error) {
1337
+ if (error.cause != null) {
1338
+ messageText.push(this.#normalizeMessage(String(error.cause)));
1339
+ }
1340
+ messageText.push(this.#normalizeMessage(String(error.message)));
1341
+ if (error.stack != null) {
1342
+ const stackLines = error.stack
1343
+ .split("\n")
1344
+ .slice(1)
1345
+ .map((line) => line.trimStart());
1346
+ messageText.push(...stackLines);
1347
+ }
1348
+ }
1349
+ return Diagnostic.error(messageText);
1350
+ }
1351
+ static isTsDiagnosticWithLocation(diagnostic) {
1352
+ return diagnostic.file != null && diagnostic.start != null && diagnostic.length != null;
1353
+ }
1354
+ static #normalizeMessage(text) {
1355
+ if (text.endsWith(".")) {
1356
+ return text;
1357
+ }
1358
+ return `${text}.`;
1359
+ }
1360
+ static warning(text, origin) {
1361
+ return new Diagnostic(text, "warning", origin);
1362
+ }
1363
+ }
1364
+
1365
+ var DiagnosticCategory;
1366
+ (function (DiagnosticCategory) {
1367
+ DiagnosticCategory["Error"] = "error";
1368
+ DiagnosticCategory["Warning"] = "warning";
1369
+ })(DiagnosticCategory || (DiagnosticCategory = {}));
1370
+
1371
1371
  class TestMember {
1372
1372
  brand;
1373
1373
  node;
@@ -1386,9 +1386,9 @@ class TestMember {
1386
1386
  if (node.arguments[0] != null && this.compiler.isStringLiteralLike(node.arguments[0])) {
1387
1387
  this.name = node.arguments[0].text;
1388
1388
  }
1389
- if (node.arguments[1] != null &&
1390
- parent.compiler.isFunctionLike(node.arguments[1]) &&
1391
- parent.compiler.isBlock(node.arguments[1].body)) {
1389
+ if (node.arguments[1] != null
1390
+ && parent.compiler.isFunctionLike(node.arguments[1])
1391
+ && parent.compiler.isBlock(node.arguments[1].body)) {
1392
1392
  const blockStart = node.arguments[1].body.getStart();
1393
1393
  const blockEnd = node.arguments[1].body.getEnd();
1394
1394
  for (const diagnostic of parent.diagnostics) {
@@ -1455,11 +1455,11 @@ class Assertion extends TestMember {
1455
1455
  const argStart = this.source[0]?.getStart();
1456
1456
  const argEnd = this.source[0]?.getEnd();
1457
1457
  for (const diagnostic of parent.diagnostics) {
1458
- if (diagnostic.start != null &&
1459
- argStart != null &&
1460
- argEnd != null &&
1461
- diagnostic.start >= argStart &&
1462
- diagnostic.start <= argEnd) {
1458
+ if (diagnostic.start != null
1459
+ && argStart != null
1460
+ && argEnd != null
1461
+ && diagnostic.start >= argStart
1462
+ && diagnostic.start <= argEnd) {
1463
1463
  this.diagnostics.add(diagnostic);
1464
1464
  parent.diagnostics.delete(diagnostic);
1465
1465
  }
@@ -1516,9 +1516,9 @@ class IdentifierLookup {
1516
1516
  };
1517
1517
  }
1518
1518
  handleImportDeclaration(node) {
1519
- if (this.#moduleSpecifiers.includes(node.moduleSpecifier.getText()) &&
1520
- node.importClause?.isTypeOnly !== true &&
1521
- node.importClause?.namedBindings != null) {
1519
+ if (this.#moduleSpecifiers.includes(node.moduleSpecifier.getText())
1520
+ && node.importClause?.isTypeOnly !== true
1521
+ && node.importClause?.namedBindings != null) {
1522
1522
  if (this.compiler.isNamedImports(node.importClause.namedBindings)) {
1523
1523
  for (const element of node.importClause.namedBindings.elements) {
1524
1524
  if (element.isTypeOnly) {
@@ -1565,8 +1565,8 @@ class IdentifierLookup {
1565
1565
  expression = expression.expression;
1566
1566
  }
1567
1567
  let identifierName;
1568
- if (this.compiler.isPropertyAccessExpression(expression) &&
1569
- expression.expression.getText() === this.#identifiers.namespace) {
1568
+ if (this.compiler.isPropertyAccessExpression(expression)
1569
+ && expression.expression.getText() === this.#identifiers.namespace) {
1570
1570
  identifierName = expression.name.getText();
1571
1571
  }
1572
1572
  else {
@@ -2029,8 +2029,8 @@ class Expect {
2029
2029
  }
2030
2030
  const sourceType = this.#getType(assertion.source[0]);
2031
2031
  const nonPrimitiveType = { flags: this.compiler.TypeFlags.NonPrimitive };
2032
- if (sourceType.flags & (this.compiler.TypeFlags.Any | this.compiler.TypeFlags.Never) ||
2033
- !this.typeChecker.isTypeAssignableTo(sourceType, nonPrimitiveType)) {
2032
+ if (sourceType.flags & (this.compiler.TypeFlags.Any | this.compiler.TypeFlags.Never)
2033
+ || !this.typeChecker.isTypeAssignableTo(sourceType, nonPrimitiveType)) {
2034
2034
  this.#onSourceArgumentMustBeObjectType(assertion.source[0], expectResult);
2035
2035
  return;
2036
2036
  }
@@ -2162,6 +2162,37 @@ class Expect {
2162
2162
  }
2163
2163
  }
2164
2164
 
2165
+ class Version {
2166
+ static isGreaterThan(source, target) {
2167
+ return !(source === target) && Version.#satisfies(source, target);
2168
+ }
2169
+ static isSatisfiedWith(source, target) {
2170
+ return source === target || Version.#satisfies(source, target);
2171
+ }
2172
+ static isVersionTag(target) {
2173
+ return /^\d+/.test(target);
2174
+ }
2175
+ static #satisfies(source, target) {
2176
+ const sourceElements = source.split(/\.|-/);
2177
+ const targetElements = target.split(/\.|-/);
2178
+ function compare(index = 0) {
2179
+ const sourceElement = sourceElements[index];
2180
+ const targetElement = targetElements[index];
2181
+ if (sourceElement > targetElement) {
2182
+ return true;
2183
+ }
2184
+ if (sourceElement < targetElement) {
2185
+ return false;
2186
+ }
2187
+ if (index === sourceElements.length - 1 || index === targetElements.length - 1) {
2188
+ return true;
2189
+ }
2190
+ return compare(index + 1);
2191
+ }
2192
+ return compare();
2193
+ }
2194
+ }
2195
+
2165
2196
  class ProjectService {
2166
2197
  compiler;
2167
2198
  #service;
@@ -2205,10 +2236,33 @@ class ProjectService {
2205
2236
  useInferredProjectPerProjectRoot: true,
2206
2237
  useSingleInferredProject: false,
2207
2238
  });
2239
+ this.#service.setCompilerOptionsForInferredProjects(this.#getDefaultCompilerOptions());
2208
2240
  }
2209
2241
  closeFile(filePath) {
2210
2242
  this.#service.closeClientFile(filePath);
2211
2243
  }
2244
+ #getDefaultCompilerOptions() {
2245
+ const defaultCompilerOptions = {
2246
+ allowJs: true,
2247
+ checkJs: true,
2248
+ esModuleInterop: true,
2249
+ jsx: "preserve",
2250
+ module: "esnext",
2251
+ moduleResolution: "node",
2252
+ resolveJsonModule: true,
2253
+ strictFunctionTypes: true,
2254
+ strictNullChecks: true,
2255
+ target: "esnext",
2256
+ };
2257
+ if (Version.isSatisfiedWith(this.compiler.version, "5.4")) {
2258
+ defaultCompilerOptions.module = "preserve";
2259
+ }
2260
+ if (Version.isSatisfiedWith(this.compiler.version, "5.0")) {
2261
+ defaultCompilerOptions["allowImportingTsExtensions"] = true;
2262
+ defaultCompilerOptions.moduleResolution = "bundler";
2263
+ }
2264
+ return defaultCompilerOptions;
2265
+ }
2212
2266
  getDefaultProject(filePath) {
2213
2267
  return this.#service.getDefaultProjectForFile(this.compiler.server.toNormalizedPath(filePath), true);
2214
2268
  }
@@ -2255,14 +2309,15 @@ class TestTreeWorker {
2255
2309
  if (member.flags & 1) {
2256
2310
  mode |= 1;
2257
2311
  }
2258
- if (member.flags & 2 ||
2259
- (this.resolvedConfig.only != null &&
2260
- member.name.toLowerCase().includes(this.resolvedConfig.only.toLowerCase())) ||
2261
- (this.#position != null && member.node.getStart() === this.#position)) {
2312
+ if (member.flags & 2
2313
+ || (this.resolvedConfig.only != null
2314
+ && member.name.toLowerCase().includes(this.resolvedConfig.only.toLowerCase()))
2315
+ || (this.#position != null && member.node.getStart() === this.#position)) {
2262
2316
  mode |= 2;
2263
2317
  }
2264
- if (member.flags & 4 ||
2265
- (this.resolvedConfig.skip != null && member.name.toLowerCase().includes(this.resolvedConfig.skip.toLowerCase()))) {
2318
+ if (member.flags & 4
2319
+ || (this.resolvedConfig.skip != null
2320
+ && member.name.toLowerCase().includes(this.resolvedConfig.skip.toLowerCase()))) {
2266
2321
  mode |= 4;
2267
2322
  }
2268
2323
  if (member.flags & 8) {
@@ -2364,8 +2419,8 @@ class TestTreeWorker {
2364
2419
  const describeResult = new DescribeResult(describe, parentResult);
2365
2420
  EventEmitter.dispatch(["describe:start", { result: describeResult }]);
2366
2421
  runMode = this.#resolveRunMode(runMode, describe);
2367
- if (!(runMode & 4 || (this.#hasOnly && !(runMode & 2)) || runMode & 8) &&
2368
- describe.diagnostics.size > 0) {
2422
+ if (!(runMode & 4 || (this.#hasOnly && !(runMode & 2)) || runMode & 8)
2423
+ && describe.diagnostics.size > 0) {
2369
2424
  EventEmitter.dispatch([
2370
2425
  "file:error",
2371
2426
  {
@@ -2525,7 +2580,7 @@ class TSTyche {
2525
2580
  #abortController = new AbortController();
2526
2581
  #storeService;
2527
2582
  #taskRunner;
2528
- static version = "1.0.0-beta.9";
2583
+ static version = "1.0.0-rc.1";
2529
2584
  constructor(resolvedConfig, storeService) {
2530
2585
  this.resolvedConfig = resolvedConfig;
2531
2586
  this.#storeService = storeService;
@@ -2535,8 +2590,8 @@ class TSTyche {
2535
2590
  #addEventHandlers() {
2536
2591
  EventEmitter.addHandler(([eventName, payload]) => {
2537
2592
  if (eventName.includes("error") || eventName.includes("fail")) {
2538
- if ("diagnostics" in payload &&
2539
- !payload.diagnostics.some(({ category }) => category === "error")) {
2593
+ if ("diagnostics" in payload
2594
+ && !payload.diagnostics.some(({ category }) => category === "error")) {
2540
2595
  return;
2541
2596
  }
2542
2597
  process.exitCode = 1;
@@ -2570,12 +2625,6 @@ class TSTyche {
2570
2625
 
2571
2626
  class OptionDefinitionsMap {
2572
2627
  static #definitions = [
2573
- {
2574
- brand: "boolean",
2575
- description: "Do not raise an error, if no test files are selected.",
2576
- group: 4 | 2,
2577
- name: "allowNoTestFiles",
2578
- },
2579
2628
  {
2580
2629
  brand: "string",
2581
2630
  description: "The path to a TSTyche configuration file.",
@@ -2714,10 +2763,10 @@ class OptionDiagnosticText {
2714
2763
  unknownOption(optionName) {
2715
2764
  return `Unknown option '${optionName}'.`;
2716
2765
  }
2717
- unknownProperty(optionName) {
2718
- return `Unknown property '${optionName}'.`;
2719
- }
2720
2766
  versionIsNotSupported(value) {
2767
+ if (value === "current") {
2768
+ return "Cannot use 'current' as a target. Failed to resolve the path to the currently installed TypeScript module.";
2769
+ }
2721
2770
  return `TypeScript version '${value}' is not supported.`;
2722
2771
  }
2723
2772
  }
@@ -2739,7 +2788,7 @@ class OptionUsageText {
2739
2788
  const supportedTagsText = `Supported tags: ${["'", supportedTags.join("', '"), "'"].join("")}.`;
2740
2789
  switch (this.#optionGroup) {
2741
2790
  case 2:
2742
- usageText.push("Argument for the '--target' option must be a single tag or a comma separated list.", "Usage examples: '--target 4.9', '--target 5.0.4', '--target 4.7,5.3.2,current'.", supportedTagsText);
2791
+ usageText.push("Argument 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'.", supportedTagsText);
2743
2792
  break;
2744
2793
  case 4:
2745
2794
  usageText.push("Item of the 'target' list must be a supported version tag.", supportedTagsText);
@@ -2908,13 +2957,10 @@ class ConfigFileOptionsWorker {
2908
2957
  this.#optionValidator = new OptionValidator(4, this.#storeService, this.#onDiagnostic);
2909
2958
  }
2910
2959
  #isDoubleQuotedString(node, sourceFile) {
2911
- return (node.kind === this.compiler.SyntaxKind.StringLiteral &&
2912
- sourceFile.text.slice(this.#skipTrivia(node.pos, sourceFile), node.end).startsWith('"'));
2960
+ return (node.kind === this.compiler.SyntaxKind.StringLiteral
2961
+ && sourceFile.text.slice(this.#skipTrivia(node.pos, sourceFile), node.end).startsWith('"'));
2913
2962
  }
2914
2963
  async parse(sourceText) {
2915
- if (sourceText === "") {
2916
- return;
2917
- }
2918
2964
  const configSourceFile = this.compiler.parseJsonText(this.#configFilePath, sourceText);
2919
2965
  if (configSourceFile.parseDiagnostics.length > 0) {
2920
2966
  for (const diagnostic of Diagnostic.fromDiagnostics(configSourceFile.parseDiagnostics, this.compiler)) {
@@ -2961,11 +3007,6 @@ class ConfigFileOptionsWorker {
2961
3007
  }
2962
3008
  async #parseOptionValue(sourceFile, valueExpression, optionDefinition, isListItem = false) {
2963
3009
  switch (valueExpression.kind) {
2964
- case this.compiler.SyntaxKind.NullKeyword:
2965
- if (optionDefinition.nullable === true) {
2966
- return null;
2967
- }
2968
- break;
2969
3010
  case this.compiler.SyntaxKind.TrueKeyword:
2970
3011
  if (optionDefinition.brand === "boolean") {
2971
3012
  return true;
@@ -3009,39 +3050,6 @@ class ConfigFileOptionsWorker {
3009
3050
  return value;
3010
3051
  }
3011
3052
  break;
3012
- case this.compiler.SyntaxKind.ObjectLiteralExpression:
3013
- if (optionDefinition.brand === "object" && "getDefinition" in optionDefinition) {
3014
- const propertyDefinition = optionDefinition.getDefinition(4);
3015
- const propertyOptions = {};
3016
- for (const property of valueExpression.properties) {
3017
- if (this.compiler.isPropertyAssignment(property)) {
3018
- if (!this.#isDoubleQuotedString(property.name, sourceFile)) {
3019
- const origin = {
3020
- end: property.end,
3021
- file: sourceFile,
3022
- start: this.#skipTrivia(property.pos, sourceFile),
3023
- };
3024
- this.#onDiagnostic(Diagnostic.error(this.#optionDiagnosticText.doubleQuotesExpected(), origin));
3025
- continue;
3026
- }
3027
- const optionName = this.#resolvePropertyName(property);
3028
- const optionDefinition = propertyDefinition.get(optionName);
3029
- if (optionDefinition) {
3030
- propertyOptions[optionDefinition.name] = await this.#parseOptionValue(sourceFile, property.initializer, optionDefinition);
3031
- }
3032
- else {
3033
- const origin = {
3034
- end: property.end,
3035
- file: sourceFile,
3036
- start: this.#skipTrivia(property.pos, sourceFile),
3037
- };
3038
- this.#onDiagnostic(Diagnostic.error(this.#optionDiagnosticText.unknownProperty(optionName), origin));
3039
- }
3040
- }
3041
- }
3042
- return propertyOptions;
3043
- }
3044
- break;
3045
3053
  }
3046
3054
  const origin = {
3047
3055
  end: valueExpression.end,
@@ -3103,10 +3111,9 @@ class ConfigService {
3103
3111
  #commandLineOptions = {};
3104
3112
  #configFileOptions = {};
3105
3113
  static #defaultOptions = {
3106
- allowNoTestFiles: false,
3107
3114
  failFast: false,
3108
- rootPath: "./",
3109
- target: [Environment.isTypeScriptInstalled ? "current" : "latest"],
3115
+ rootPath: Path.resolve("./"),
3116
+ target: [Environment.typescriptPath == null ? "latest" : "current"],
3110
3117
  testFileMatch: ["**/*.tst.*", "**/__typetests__/*.test.*", "**/typetests/*.test.*"],
3111
3118
  };
3112
3119
  #pathMatch = [];
@@ -3133,17 +3140,17 @@ class ConfigService {
3133
3140
  const commandLineWorker = new CommandLineOptionsWorker(this.#commandLineOptions, this.#pathMatch, this.#storeService, this.#onDiagnostic);
3134
3141
  await commandLineWorker.parse(commandLineArgs);
3135
3142
  }
3136
- async readConfigFile(filePath, sourceText) {
3137
- const configFilePath = filePath ?? this.#commandLineOptions.config ?? Path.resolve("./tstyche.config.json");
3143
+ async readConfigFile() {
3144
+ const configFilePath = this.#commandLineOptions.config ?? Path.resolve("./tstyche.config.json");
3145
+ if (!existsSync(configFilePath)) {
3146
+ return;
3147
+ }
3138
3148
  this.#configFileOptions = {
3139
3149
  rootPath: Path.dirname(configFilePath),
3140
3150
  };
3141
- let configFileText = sourceText ?? "";
3142
- if (sourceText == null && existsSync(configFilePath)) {
3143
- configFileText = await fs.readFile(configFilePath, {
3144
- encoding: "utf8",
3145
- });
3146
- }
3151
+ const configFileText = await fs.readFile(configFilePath, {
3152
+ encoding: "utf8",
3153
+ });
3147
3154
  const configFileWorker = new ConfigFileOptionsWorker(this.compiler, this.#configFileOptions, configFilePath, this.#storeService, this.#onDiagnostic);
3148
3155
  await configFileWorker.parse(configFileText);
3149
3156
  }
@@ -3157,15 +3164,15 @@ class ConfigService {
3157
3164
  return mergedOptions;
3158
3165
  }
3159
3166
  selectTestFiles() {
3160
- const { allowNoTestFiles, pathMatch, rootPath, testFileMatch } = this.resolveConfig();
3161
- let testFilePaths = this.compiler.sys.readDirectory(rootPath, undefined, undefined, testFileMatch);
3167
+ const { pathMatch, rootPath, testFileMatch } = this.resolveConfig();
3168
+ let testFilePaths = this.compiler.sys.readDirectory(rootPath, ["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs"], undefined, testFileMatch);
3162
3169
  if (pathMatch.length > 0) {
3163
3170
  testFilePaths = testFilePaths.filter((testFilePath) => pathMatch.some((match) => {
3164
3171
  const relativeTestFilePath = Path.relative("", testFilePath);
3165
3172
  return relativeTestFilePath.toLowerCase().includes(match.toLowerCase());
3166
3173
  }));
3167
3174
  }
3168
- if (testFilePaths.length === 0 && !allowNoTestFiles) {
3175
+ if (testFilePaths.length === 0) {
3169
3176
  const text = [
3170
3177
  "No test files were selected using current configuration.",
3171
3178
  `Root path: ${rootPath}`,
@@ -3187,7 +3194,6 @@ var OptionBrand;
3187
3194
  OptionBrand["Boolean"] = "boolean";
3188
3195
  OptionBrand["True"] = "true";
3189
3196
  OptionBrand["List"] = "list";
3190
- OptionBrand["Object"] = "object";
3191
3197
  })(OptionBrand || (OptionBrand = {}));
3192
3198
 
3193
3199
  var OptionGroup;
@@ -3226,6 +3232,7 @@ class ManifestWorker {
3226
3232
  }, (result) => {
3227
3233
  if (result.statusCode !== 200) {
3228
3234
  reject(new Error(`Request failed with status code ${String(result.statusCode)}.`));
3235
+ result.resume();
3229
3236
  return;
3230
3237
  }
3231
3238
  result.setEncoding("utf8");
@@ -3275,7 +3282,7 @@ class ManifestWorker {
3275
3282
  }
3276
3283
  catch (error) {
3277
3284
  if (!options.quite) {
3278
- const text = [`Failed to fetch metadata of the 'typescript' package from '${this.#registryUrl.href}'.`];
3285
+ const text = [`Failed to fetch metadata of the 'typescript' package from '${this.#registryUrl.toString()}'.`];
3279
3286
  if (error instanceof Error && error.name !== "AbortError") {
3280
3287
  text.push("Might be there is an issue with the registry or the network connection.");
3281
3288
  }
@@ -3331,8 +3338,8 @@ class ManifestWorker {
3331
3338
  const quite = options?.refresh !== true;
3332
3339
  const freshManifest = await this.#load(signal, { quite });
3333
3340
  if (freshManifest != null) {
3334
- manifest = { ...manifest, ...freshManifest };
3335
- await this.persist(manifest);
3341
+ await this.persist(freshManifest);
3342
+ return freshManifest;
3336
3343
  }
3337
3344
  }
3338
3345
  return manifest;
@@ -3388,28 +3395,6 @@ class Lock {
3388
3395
  }
3389
3396
  }
3390
3397
 
3391
- class Version {
3392
- static satisfies(source, target) {
3393
- const sourceElements = source.split(/\.|-/);
3394
- const targetElements = target.split(/\.|-/);
3395
- function compare(index = 0) {
3396
- const sourceElement = sourceElements[index];
3397
- const targetElement = targetElements[index];
3398
- if (sourceElement > targetElement) {
3399
- return true;
3400
- }
3401
- if (sourceElement === targetElement) {
3402
- if (index === targetElements.length - 1) {
3403
- return true;
3404
- }
3405
- return compare(index + 1);
3406
- }
3407
- return false;
3408
- }
3409
- return compare();
3410
- }
3411
- }
3412
-
3413
3398
  class PackageInstaller {
3414
3399
  #onDiagnostic;
3415
3400
  #readyFileName = "__ready__";
@@ -3455,10 +3440,7 @@ class PackageInstaller {
3455
3440
  this.#onDiagnostic(Diagnostic.fromError(`Failed to install 'typescript@${compilerVersion}'.`, error));
3456
3441
  }
3457
3442
  }
3458
- if (Version.satisfies(compilerVersion, "5.3")) {
3459
- return Path.join(installationPath, "node_modules", "typescript", "lib", "typescript.js");
3460
- }
3461
- return Path.join(installationPath, "node_modules", "typescript", "lib", "tsserverlibrary.js");
3443
+ return Path.join(installationPath, "node_modules", "typescript", "lib", "typescript.js");
3462
3444
  }
3463
3445
  async #install(cwd, signal) {
3464
3446
  const args = ["install", "--ignore-scripts", "--no-bin-links", "--no-package-lock"];
@@ -3490,7 +3472,6 @@ class StoreService {
3490
3472
  #compilerInstanceCache = new Map();
3491
3473
  #manifest;
3492
3474
  #manifestWorker;
3493
- #nodeRequire = createRequire(import.meta.url);
3494
3475
  #packageInstaller;
3495
3476
  #storePath;
3496
3477
  constructor() {
@@ -3521,19 +3502,11 @@ class StoreService {
3521
3502
  if (compilerInstance != null) {
3522
3503
  return compilerInstance;
3523
3504
  }
3524
- const modulePaths = [];
3525
- if (tag === "current") {
3526
- try {
3527
- modulePaths.push(this.#nodeRequire.resolve("typescript/lib/tsserverlibrary.js"), this.#nodeRequire.resolve("typescript"));
3528
- }
3529
- catch (error) {
3530
- this.#onDiagnostic(Diagnostic.fromError("Failed to resolve locally installed 'typescript' package. It might be not installed.", error));
3531
- }
3505
+ let modulePath;
3506
+ if (tag === "current" && Environment.typescriptPath != null) {
3507
+ modulePath = Environment.typescriptPath;
3532
3508
  }
3533
- if (modulePaths.length === 0) {
3534
- if (tag === "current") {
3535
- return;
3536
- }
3509
+ else {
3537
3510
  const version = await this.resolveTag(tag, signal);
3538
3511
  if (version == null) {
3539
3512
  this.#onDiagnostic(Diagnostic.error(`Cannot add the 'typescript' package for the '${tag}' tag.`));
@@ -3543,31 +3516,27 @@ class StoreService {
3543
3516
  if (compilerInstance != null) {
3544
3517
  return compilerInstance;
3545
3518
  }
3546
- const installedModulePath = await this.#packageInstaller.ensure(version, signal);
3547
- if (installedModulePath != null) {
3548
- modulePaths.push(installedModulePath);
3549
- }
3519
+ modulePath = await this.#packageInstaller.ensure(version, signal);
3550
3520
  }
3551
- if (modulePaths.length !== 0) {
3552
- compilerInstance = await this.#loadModule(modulePaths);
3521
+ if (modulePath != null) {
3522
+ compilerInstance = await this.#loadModule(modulePath);
3553
3523
  this.#compilerInstanceCache.set(tag, compilerInstance);
3554
3524
  this.#compilerInstanceCache.set(compilerInstance.version, compilerInstance);
3555
- return compilerInstance;
3556
3525
  }
3557
- return;
3526
+ return compilerInstance;
3558
3527
  }
3559
- async #loadModule(modulePaths) {
3528
+ async #loadModule(modulePath) {
3560
3529
  const exports = {};
3561
3530
  const module = { exports };
3562
- for (const modulePath of modulePaths) {
3563
- const require = createRequire(modulePath);
3564
- let sourceText = await fs.readFile(modulePath, { encoding: "utf8" });
3565
- if (sourceText.length < 3000) {
3531
+ const candidatePaths = [Path.join(Path.dirname(modulePath), "tsserverlibrary.js"), modulePath];
3532
+ for (const candidatePath of candidatePaths) {
3533
+ const sourceText = await fs.readFile(candidatePath, { encoding: "utf8" });
3534
+ const modifiedSourceText = sourceText.replace("return checker;", "return { ...checker, isTypeIdenticalTo, isTypeSubtypeOf };");
3535
+ if (modifiedSourceText.length === sourceText.length) {
3566
3536
  continue;
3567
3537
  }
3568
- sourceText = sourceText.replace("isTypeAssignableTo,", "isTypeAssignableTo, isTypeIdenticalTo, isTypeSubtypeOf,");
3569
- const compiledWrapper = vm.compileFunction(sourceText, ["exports", "require", "module", "__filename", "__dirname"], { filename: modulePath });
3570
- compiledWrapper(exports, require, module, modulePath, Path.dirname(modulePath));
3538
+ const compiledWrapper = vm.compileFunction(modifiedSourceText, ["exports", "require", "module", "__filename", "__dirname"], { filename: candidatePath });
3539
+ compiledWrapper(exports, createRequire(candidatePath), module, candidatePath, Path.dirname(candidatePath));
3571
3540
  break;
3572
3541
  }
3573
3542
  return module.exports;
@@ -3595,48 +3564,36 @@ class StoreService {
3595
3564
  if (this.#manifest.versions.includes(tag)) {
3596
3565
  return tag;
3597
3566
  }
3598
- const version = this.#manifest.resolutions[tag];
3599
- if (this.#manifestWorker.isOutdated(this.#manifest, 60) &&
3600
- Object.keys(this.#manifest.resolutions).slice(-5).includes(tag)) {
3601
- this.#onDiagnostic(Diagnostic.warning([
3602
- "Failed to update metadata of the 'typescript' package from the registry.",
3603
- `The resolution of the '${tag}' tag may be outdated.`,
3604
- ]));
3605
- }
3606
- return version;
3567
+ return this.#manifest.resolutions[tag];
3607
3568
  }
3608
3569
  async update(signal) {
3609
3570
  await this.#manifestWorker.open(signal, { refresh: true });
3610
3571
  }
3611
3572
  async validateTag(tag, signal) {
3612
3573
  if (tag === "current") {
3613
- return true;
3574
+ return Environment.typescriptPath != null;
3614
3575
  }
3615
3576
  await this.open(signal);
3616
3577
  if (!this.#manifest) {
3617
3578
  return false;
3618
3579
  }
3619
- if (this.#manifest.versions.includes(tag) || tag in this.#manifest.resolutions || tag === "current") {
3620
- return true;
3621
- }
3622
- if (this.#manifest.resolutions["latest"] != null &&
3623
- tag.startsWith(this.#manifest.resolutions["latest"].slice(0, 3))) {
3580
+ if (this.#manifestWorker.isOutdated(this.#manifest, 60)
3581
+ && (!Version.isVersionTag(tag)
3582
+ || (this.#manifest.resolutions["latest"] != null
3583
+ && Version.isGreaterThan(tag, this.#manifest.resolutions["latest"])))) {
3624
3584
  this.#onDiagnostic(Diagnostic.warning([
3625
3585
  "Failed to update metadata of the 'typescript' package from the registry.",
3626
3586
  `The resolution of the '${tag}' tag may be outdated.`,
3627
3587
  ]));
3628
3588
  }
3629
- return false;
3589
+ return this.#manifest.versions.includes(tag) || tag in this.#manifest.resolutions || tag === "current";
3630
3590
  }
3631
3591
  }
3632
3592
 
3633
3593
  class Cli {
3634
- #abortController = new AbortController();
3635
3594
  #logger;
3636
- #process;
3637
3595
  #storeService;
3638
- constructor(process) {
3639
- this.#process = process;
3596
+ constructor() {
3640
3597
  this.#logger = new Logger();
3641
3598
  this.#storeService = new StoreService();
3642
3599
  }
@@ -3650,8 +3607,7 @@ class Cli {
3650
3607
  for (const diagnostic of payload.diagnostics) {
3651
3608
  switch (diagnostic.category) {
3652
3609
  case "error":
3653
- this.#abortController.abort();
3654
- this.#process.exitCode = 1;
3610
+ process.exitCode = 1;
3655
3611
  this.#logger.writeError(diagnosticText(diagnostic));
3656
3612
  break;
3657
3613
  case "warning":
@@ -3678,48 +3634,50 @@ class Cli {
3678
3634
  return;
3679
3635
  }
3680
3636
  if (commandLineArguments.includes("--update")) {
3681
- await this.#storeService.update(this.#abortController.signal);
3637
+ await this.#storeService.update();
3682
3638
  return;
3683
3639
  }
3684
- if (this.#process.exitCode === 1) {
3685
- return;
3686
- }
3687
- const compiler = await this.#storeService.load(Environment.isTypeScriptInstalled ? "current" : "latest", this.#abortController.signal);
3640
+ const compiler = await this.#storeService.load(Environment.typescriptPath == null ? "latest" : "current");
3688
3641
  if (!compiler) {
3689
3642
  return;
3690
3643
  }
3691
3644
  const configService = new ConfigService(compiler, this.#storeService);
3692
3645
  await configService.parseCommandLine(commandLineArguments);
3693
- if (this.#process.exitCode === 1) {
3646
+ if (process.exitCode === 1) {
3694
3647
  return;
3695
3648
  }
3696
3649
  await configService.readConfigFile();
3697
- if (this.#process.exitCode === 1) {
3650
+ if (process.exitCode === 1) {
3698
3651
  return;
3699
3652
  }
3700
3653
  const resolvedConfig = configService.resolveConfig();
3701
3654
  if (configService.commandLineOptions.showConfig === true) {
3702
3655
  this.#logger.writeMessage(formattedText({
3703
3656
  noColor: Environment.noColor,
3657
+ noInteractive: Environment.noInteractive,
3704
3658
  storePath: Environment.storePath,
3705
3659
  timeout: Environment.timeout,
3660
+ typescriptPath: Environment.typescriptPath,
3706
3661
  ...resolvedConfig,
3707
3662
  }));
3708
3663
  return;
3709
3664
  }
3710
3665
  if (configService.commandLineOptions.install === true) {
3711
3666
  for (const tag of resolvedConfig.target) {
3712
- await this.#storeService.install(tag, this.#abortController.signal);
3667
+ await this.#storeService.install(tag);
3713
3668
  }
3714
3669
  return;
3715
3670
  }
3716
- const testFiles = configService.selectTestFiles();
3717
- if (this.#process.exitCode === 1) {
3718
- return;
3719
- }
3720
- if (configService.commandLineOptions.listFiles === true) {
3721
- this.#logger.writeMessage(formattedText(testFiles));
3722
- return;
3671
+ let testFiles = [];
3672
+ if (resolvedConfig.testFileMatch.length !== 0) {
3673
+ testFiles = configService.selectTestFiles();
3674
+ if (testFiles.length === 0) {
3675
+ return;
3676
+ }
3677
+ if (configService.commandLineOptions.listFiles === true) {
3678
+ this.#logger.writeMessage(formattedText(testFiles));
3679
+ return;
3680
+ }
3723
3681
  }
3724
3682
  EventEmitter.removeHandler(this.#onStartupEvent);
3725
3683
  const tstyche = new TSTyche(resolvedConfig, this.#storeService);
@@ -3727,4 +3685,4 @@ class Cli {
3727
3685
  }
3728
3686
  }
3729
3687
 
3730
- export { Assertion, Cli, CollectService, Color, ConfigService, DescribeResult, Diagnostic, DiagnosticCategory, Environment, EventEmitter, Expect, ExpectResult, FileResult, Line, Logger, OptionBrand, OptionDefinitionsMap, OptionGroup, Path, ProjectResult, ProjectService, Reporter, Result, ResultCount, ResultManager, ResultStatus, ResultTiming, Scribbler, StoreService, SummaryReporter, TSTyche, TargetResult, TaskRunner, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, ThoroughReporter, addsPackageStepText, describeNameText, diagnosticText, fileStatusText, fileViewText, formattedText, helpText, summaryText, testNameText, usesCompilerStepText };
3688
+ export { Assertion, Cli, CollectService, Color, ConfigService, DescribeResult, Diagnostic, DiagnosticCategory, Environment, EventEmitter, Expect, ExpectResult, FileResult, Line, Logger, OptionBrand, OptionDefinitionsMap, OptionGroup, Path, ProjectResult, ProjectService, Reporter, Result, ResultCount, ResultManager, ResultStatus, ResultTiming, Scribbler, StoreService, SummaryReporter, TSTyche, TargetResult, TaskRunner, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, ThoroughReporter, Version, addsPackageStepText, describeNameText, diagnosticText, fileStatusText, fileViewText, formattedText, helpText, summaryText, testNameText, usesCompilerStepText };