tstyche 6.1.0 → 7.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tag.js CHANGED
@@ -25,12 +25,9 @@ async function tstyche(template, ...substitutions) {
25
25
  eventEmitter.addHandler(statusHandler);
26
26
  await cli.run(commandLine, new CancellationToken());
27
27
  eventEmitter.removeHandler(statusHandler);
28
- return new Promise((resolve, reject) => {
29
- if (statusHandler.hasError()) {
30
- reject(new Error("TSTyche test run failed. Check the output above for details."));
31
- }
32
- resolve();
33
- });
28
+ if (statusHandler.hasError()) {
29
+ throw new Error("TSTyche test run failed. Check the output above for details.");
30
+ }
34
31
  }
35
32
 
36
33
  export { tstyche as default };
package/dist/tstyche.d.ts CHANGED
@@ -156,6 +156,7 @@ interface CommandLineOptions {
156
156
  target?: Array<string>;
157
157
  tsconfig?: string;
158
158
  update?: boolean;
159
+ verbose?: boolean;
159
160
  version?: boolean;
160
161
  watch?: boolean;
161
162
  }
@@ -168,10 +169,10 @@ interface ConfigFileOptions {
168
169
  rejectAnyType?: boolean;
169
170
  rejectNeverType?: boolean;
170
171
  reporters?: Array<string>;
171
- rootPath?: string;
172
172
  target?: Array<string>;
173
173
  testFileMatch?: Array<string>;
174
174
  tsconfig?: string;
175
+ verbose?: boolean;
175
176
  }
176
177
 
177
178
  interface InlineConfig {
@@ -181,9 +182,10 @@ interface InlineConfig {
181
182
  };
182
183
  template?: boolean;
183
184
  }
184
- interface ResolvedConfig extends Omit<CommandLineOptions, "config" | keyof ConfigFileOptions>, Required<ConfigFileOptions> {
185
+ interface ResolvedConfig extends Omit<CommandLineOptions, "config" | "root" | keyof ConfigFileOptions>, Required<ConfigFileOptions> {
185
186
  configFilePath: string;
186
187
  pathMatch: Array<string>;
188
+ rootPath: string;
187
189
  }
188
190
  interface TextRange {
189
191
  start: number;
@@ -203,17 +205,16 @@ declare class Config {
203
205
  commandLineOptions: CommandLineOptions;
204
206
  pathMatch: Array<string>;
205
207
  }>;
206
- static parseConfigFile(configPath?: string, rootPath?: string): Promise<{
208
+ static parseConfigFile(configPath?: string | undefined, rootPath?: string | undefined): Promise<{
207
209
  configFileOptions: ConfigFileOptions;
208
- configFilePath: string;
209
210
  }>;
210
211
  static resolve(options?: {
211
212
  configFileOptions?: ConfigFileOptions;
212
- configFilePath?: string;
213
- commandLineOptions?: Omit<CommandLineOptions, "config">;
213
+ commandLineOptions?: CommandLineOptions;
214
214
  pathMatch?: Array<string>;
215
215
  }): ResolvedConfig;
216
- static resolveConfigFilePath(configPath?: string, rootPath?: string): string;
216
+ static resolveConfigFilePath(configPath?: string | undefined, rootPath?: string | undefined): string;
217
+ static resolveRootPath(rootPath?: string | undefined): string;
217
218
  }
218
219
 
219
220
  declare enum OptionBrand {
@@ -281,6 +282,7 @@ type OptionDefinition = PrimitiveTypeOptionDefinition | ListTypeOptionDefinition
281
282
  declare class Options {
282
283
  #private;
283
284
  static for(optionGroup: OptionGroup): Map<string, OptionDefinition>;
285
+ static isJsonString(text: string): boolean;
284
286
  static resolve(optionName: string, optionValue: string, rootPath?: string): string;
285
287
  static validate(optionName: string, optionValue: string, onDiagnostics: DiagnosticsHandler, origin?: DiagnosticOrigin): Promise<void>;
286
288
  }
@@ -308,6 +310,11 @@ declare abstract class BaseReporter implements Reporter {
308
310
  abstract on([event, payload]: ReporterEvent): void;
309
311
  }
310
312
 
313
+ declare class DotReporter extends BaseReporter {
314
+ #private;
315
+ on([event, payload]: ReporterEvent): void;
316
+ }
317
+
311
318
  declare class ListReporter extends BaseReporter {
312
319
  #private;
313
320
  on([event, payload]: ReporterEvent): void;
@@ -325,6 +332,13 @@ declare class WatchReporter extends BaseReporter {
325
332
  on([event, payload]: ReporterEvent): void;
326
333
  }
327
334
 
335
+ declare enum ProjectConfigKind {
336
+ Discovered = 0,
337
+ Default = 1,
338
+ Provided = 2,
339
+ Synthetic = 3
340
+ }
341
+
328
342
  declare enum ResultStatus {
329
343
  Runs = "runs",
330
344
  Passed = "passed",
@@ -336,6 +350,10 @@ declare enum ResultStatus {
336
350
  Todo = "todo"
337
351
  }
338
352
 
353
+ type ProjectConfig = {
354
+ kind: ProjectConfigKind;
355
+ specifier: string;
356
+ };
339
357
  type TargetResultStatus = ResultStatus.Runs | ResultStatus.Passed | ResultStatus.Failed;
340
358
  type TargetCounts = {
341
359
  [K in Exclude<TargetResultStatus, ResultStatus.Runs>]: number;
@@ -408,9 +426,9 @@ declare class FileResult {
408
426
 
409
427
  declare class ProjectResult {
410
428
  compilerVersion: string;
411
- projectConfigFilePath: string | undefined;
429
+ projectConfig: ProjectConfig;
412
430
  results: Array<FileResult>;
413
- constructor(compilerVersion: string, projectConfigFilePath: string | undefined);
431
+ constructor(compilerVersion: string, projectConfig: ProjectConfig);
414
432
  }
415
433
 
416
434
  declare class TargetResult {
@@ -461,7 +479,7 @@ type Event = ["config:error", {
461
479
  result: TargetResult;
462
480
  }] | ["project:uses", {
463
481
  compilerVersion: string;
464
- projectConfigFilePath: string | undefined;
482
+ projectConfig: ProjectConfig;
465
483
  }] | ["project:error", {
466
484
  diagnostics: Array<Diagnostic>;
467
485
  }] | ["file:start", {
@@ -592,7 +610,9 @@ interface TextProps {
592
610
  }
593
611
  declare function Text({ children, color, indent }: TextProps): ScribblerJsx.Element;
594
612
 
595
- declare function addsPackageText(packageVersion: string, packagePath: string): ScribblerJsx.Element;
613
+ declare function addsText(packageVersion: string, packagePath: string, options?: {
614
+ short?: boolean;
615
+ }): ScribblerJsx.Element;
596
616
 
597
617
  declare function describeNameText(name: string, indent?: number): ScribblerJsx.Element;
598
618
 
@@ -604,9 +624,9 @@ interface CodeFrameOptions {
604
624
 
605
625
  declare function diagnosticText(diagnostic: Diagnostic, codeFrameOptions?: CodeFrameOptions): ScribblerJsx.Element;
606
626
 
607
- declare function fileStatusText(status: FileResultStatus, file: FileLocation): ScribblerJsx.Element;
627
+ declare function dotText(status: ResultStatus): ScribblerJsx.Element;
608
628
 
609
- declare function fileViewText(lines: Array<ScribblerJsx.Element>, addEmptyFinalLine: boolean): ScribblerJsx.Element;
629
+ declare function fileStatusText(status: FileResultStatus, file: FileLocation): ScribblerJsx.Element;
610
630
 
611
631
  declare function formattedText(input: string | Array<string> | Record<string, unknown>): ScribblerJsx.Element;
612
632
 
@@ -626,6 +646,7 @@ declare class OutputService {
626
646
  static outputStream: StreamController;
627
647
  static clearTerminal(): void;
628
648
  static eraseLastLine(): void;
649
+ static writeBlankLine(count?: number): void;
629
650
  static writeError(element: ScribblerJsx.Element | Array<ScribblerJsx.Element>): void;
630
651
  static writeMessage(element: ScribblerJsx.Element | Array<ScribblerJsx.Element>): void;
631
652
  static writeWarning(element: ScribblerJsx.Element | Array<ScribblerJsx.Element>): void;
@@ -645,8 +666,8 @@ declare function summaryText({ targetCounts, fileCounts, testCounts, assertionCo
645
666
 
646
667
  declare function testNameText(status: Exclude<TestResultStatus, ResultStatus.Runs>, name: string, indent?: number): ScribblerJsx.Element;
647
668
 
648
- declare function usesCompilerText(compilerVersion: string, projectConfigFilePath: string | undefined, options?: {
649
- prependEmptyLine: boolean;
669
+ declare function usesText(compilerVersion: string, projectConfig: ProjectConfig, options?: {
670
+ short?: boolean;
650
671
  }): ScribblerJsx.Element;
651
672
 
652
673
  declare function waitingForFileChangesText(): ScribblerJsx.Element;
@@ -732,5 +753,5 @@ declare class Version {
732
753
  static isSatisfiedWith(source: string, target: string): boolean;
733
754
  }
734
755
 
735
- export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectResult, Result, ResultStatus, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, Store, StreamController, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
736
- export type { AssertionCounts, AssertionResultStatus, CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, EnvironmentOptions, Event, EventHandler, FileCounts, FileResultStatus, InlineConfig, ItemDefinition, OptionDefinition, Reporter, ReporterEvent, ResolvedConfig, ResultCounts, ResultTiming, ScribblerOptions, SuppressedCounts, SuppressedResultStatus, TargetCounts, TargetResultStatus, TestCounts, TestResultStatus, TextRange };
756
+ export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, DotReporter, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectConfigKind, ProjectResult, Result, ResultStatus, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, Store, StreamController, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, dotText, environmentOptions, fileStatusText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesText, waitingForFileChangesText, watchUsageText };
757
+ export type { AssertionCounts, AssertionResultStatus, CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, EnvironmentOptions, Event, EventHandler, FileCounts, FileResultStatus, InlineConfig, ItemDefinition, OptionDefinition, ProjectConfig, Reporter, ReporterEvent, ResolvedConfig, ResultCounts, ResultTiming, ScribblerOptions, SuppressedCounts, SuppressedResultStatus, TargetCounts, TargetResultStatus, TestCounts, TestResultStatus, TextRange };
package/dist/tstyche.js CHANGED
@@ -60,7 +60,7 @@ class JsonNode {
60
60
  return undefined;
61
61
  }
62
62
  if (/^['"]/.test(this.text)) {
63
- return this.text.slice(1, -1);
63
+ return this.text.slice(1, -1).replaceAll("\\", "");
64
64
  }
65
65
  if (options?.expectsIdentifier) {
66
66
  return this.text;
@@ -244,7 +244,8 @@ class JsonScanner {
244
244
  }
245
245
  while (!this.isRead()) {
246
246
  text += this.#readCharacter();
247
- if (text.slice(-1) === closingTokenText || (!closingTokenText && /[\s,:\]}]/.test(this.#peekCharacter()))) {
247
+ if ((text.at(-2) !== "\\" && text.at(-1) === closingTokenText) ||
248
+ (!closingTokenText && /[\s,:\]}]/.test(this.#peekCharacter()))) {
248
249
  break;
249
250
  }
250
251
  }
@@ -375,7 +376,7 @@ class ConfigDiagnosticText {
375
376
  static fileMatchPatternCannotStartWith(optionName, segment) {
376
377
  return [
377
378
  `A '${optionName}' pattern cannot start with '${segment}'.`,
378
- "The files are only collected within the 'rootPath' directory.",
379
+ "The files are only collected within the root directory.",
379
380
  ];
380
381
  }
381
382
  static inspectSupportedVersions() {
@@ -1083,7 +1084,7 @@ class Options {
1083
1084
  },
1084
1085
  {
1085
1086
  brand: "true",
1086
- description: "Print the list of the selected test files and exit.",
1087
+ description: "Print the list of selected test files and exit.",
1087
1088
  group: 2,
1088
1089
  name: "listFiles",
1089
1090
  },
@@ -1133,12 +1134,6 @@ class Options {
1133
1134
  group: 2,
1134
1135
  name: "root",
1135
1136
  },
1136
- {
1137
- brand: "string",
1138
- description: "The path to a directory containing files of a test project.",
1139
- group: 4,
1140
- name: "rootPath",
1141
- },
1142
1137
  {
1143
1138
  brand: "true",
1144
1139
  description: "Print the resolved configuration and exit.",
@@ -1153,7 +1148,7 @@ class Options {
1153
1148
  },
1154
1149
  {
1155
1150
  brand: "range",
1156
- description: "The range of TypeScript versions to be tested against.",
1151
+ description: "The range of TypeScript versions to test against.",
1157
1152
  group: 2 | 4 | 8,
1158
1153
  name: "target",
1159
1154
  },
@@ -1169,7 +1164,7 @@ class Options {
1169
1164
  },
1170
1165
  {
1171
1166
  brand: "string",
1172
- description: "The look up strategy to be used to find the TSConfig file.",
1167
+ description: "The TSConfig to load.",
1173
1168
  group: 2 | 4,
1174
1169
  name: "tsconfig",
1175
1170
  },
@@ -1179,6 +1174,12 @@ class Options {
1179
1174
  group: 2,
1180
1175
  name: "update",
1181
1176
  },
1177
+ {
1178
+ brand: "boolean",
1179
+ description: "Enable detailed logging.",
1180
+ group: 2 | 4,
1181
+ name: "verbose",
1182
+ },
1182
1183
  {
1183
1184
  brand: "true",
1184
1185
  description: "Print the version number and exit.",
@@ -1205,19 +1206,22 @@ class Options {
1205
1206
  return optionName.startsWith("--") ? optionName.slice(2) : optionName;
1206
1207
  }
1207
1208
  static #isBuiltinReporter(optionValue) {
1208
- return ["list", "summary"].includes(optionValue);
1209
+ return ["dot", "list", "summary"].includes(optionValue);
1209
1210
  }
1210
1211
  static #isLookupStrategy(optionValue) {
1211
- return ["findup", "ignore"].includes(optionValue);
1212
+ return ["findup", "baseline"].includes(optionValue);
1213
+ }
1214
+ static isJsonString(text) {
1215
+ return text.startsWith("{");
1212
1216
  }
1213
1217
  static resolve(optionName, optionValue, rootPath = ".") {
1214
1218
  const canonicalOptionName = Options.#getCanonicalOptionName(optionName);
1215
1219
  switch (canonicalOptionName) {
1216
1220
  case "config":
1217
1221
  case "root":
1218
- case "rootPath":
1219
1222
  case "tsconfig":
1220
- if (canonicalOptionName === "tsconfig" && Options.#isLookupStrategy(optionValue)) {
1223
+ if (canonicalOptionName === "tsconfig" &&
1224
+ (Options.#isLookupStrategy(optionValue) || Options.isJsonString(optionValue))) {
1221
1225
  break;
1222
1226
  }
1223
1227
  if (optionValue.startsWith("file:")) {
@@ -1226,7 +1230,7 @@ class Options {
1226
1230
  optionValue = Path.resolve(rootPath, optionValue);
1227
1231
  break;
1228
1232
  case "reporters":
1229
- if (canonicalOptionName === "reporters" && Options.#isBuiltinReporter(optionValue)) {
1233
+ if (Options.#isBuiltinReporter(optionValue)) {
1230
1234
  break;
1231
1235
  }
1232
1236
  try {
@@ -1248,9 +1252,9 @@ class Options {
1248
1252
  switch (canonicalOptionName) {
1249
1253
  case "config":
1250
1254
  case "root":
1251
- case "rootPath":
1252
1255
  case "tsconfig":
1253
- if (canonicalOptionName === "tsconfig" && Options.#isLookupStrategy(optionValue)) {
1256
+ if (canonicalOptionName === "tsconfig" &&
1257
+ (Options.#isLookupStrategy(optionValue) || Options.isJsonString(optionValue))) {
1254
1258
  break;
1255
1259
  }
1256
1260
  if (existsSync(optionValue)) {
@@ -1259,7 +1263,7 @@ class Options {
1259
1263
  onDiagnostics(Diagnostic.error(ConfigDiagnosticText.fileDoesNotExist(optionValue), origin));
1260
1264
  break;
1261
1265
  case "reporters":
1262
- if (canonicalOptionName === "reporters" && Options.#isBuiltinReporter(optionValue)) {
1266
+ if (Options.#isBuiltinReporter(optionValue)) {
1263
1267
  break;
1264
1268
  }
1265
1269
  if (optionValue.startsWith("file:") && existsSync(new URL(optionValue))) {
@@ -1574,10 +1578,10 @@ const defaultOptions = {
1574
1578
  rejectAnyType: true,
1575
1579
  rejectNeverType: true,
1576
1580
  reporters: ["list", "summary"],
1577
- rootPath: Path.resolve("./"),
1578
1581
  target: ["*"],
1579
1582
  testFileMatch: ["**/*.tst.*", "**/__typetests__/*.test.*", "**/typetests/*.test.*"],
1580
1583
  tsconfig: "findup",
1584
+ verbose: false,
1581
1585
  };
1582
1586
 
1583
1587
  class Config {
@@ -1592,10 +1596,8 @@ class Config {
1592
1596
  return { commandLineOptions, pathMatch };
1593
1597
  }
1594
1598
  static async parseConfigFile(configPath, rootPath) {
1599
+ const configFileOptions = {};
1595
1600
  const configFilePath = Config.resolveConfigFilePath(configPath, rootPath);
1596
- const configFileOptions = {
1597
- rootPath: rootPath ?? Path.dirname(configFilePath),
1598
- };
1599
1601
  if (existsSync(configFilePath)) {
1600
1602
  const configFileText = await fs.readFile(configFilePath, {
1601
1603
  encoding: "utf8",
@@ -1604,12 +1606,13 @@ class Config {
1604
1606
  const configFileParser = new ConfigParser(configFileOptions, 4, sourceFile, new JsonScanner(sourceFile), Config.#onDiagnostics);
1605
1607
  await configFileParser.parse();
1606
1608
  }
1607
- return { configFileOptions, configFilePath };
1609
+ return { configFileOptions };
1608
1610
  }
1609
1611
  static resolve(options) {
1610
1612
  const resolvedConfig = {
1611
- configFilePath: Config.resolveConfigFilePath(options?.configFilePath),
1613
+ configFilePath: Config.resolveConfigFilePath(options?.commandLineOptions?.config, options?.commandLineOptions?.root),
1612
1614
  pathMatch: options?.pathMatch ?? [],
1615
+ rootPath: Config.resolveRootPath(options?.commandLineOptions?.root),
1613
1616
  ...defaultOptions,
1614
1617
  ...options?.configFileOptions,
1615
1618
  ...options?.commandLineOptions,
@@ -1622,11 +1625,13 @@ class Config {
1622
1625
  }
1623
1626
  return resolvedConfig;
1624
1627
  }
1625
- static resolveConfigFilePath(configPath, rootPath = ".") {
1626
- if (configPath != null) {
1627
- return Path.resolve(configPath);
1628
- }
1629
- return Path.resolve(rootPath, "./tstyche.config.json");
1628
+ static resolveConfigFilePath(configPath, rootPath) {
1629
+ return configPath != null
1630
+ ? Path.resolve(configPath)
1631
+ : Path.resolve(Config.resolveRootPath(rootPath), "./tstyche.json");
1632
+ }
1633
+ static resolveRootPath(rootPath) {
1634
+ return Path.resolve(rootPath ?? ".");
1630
1635
  }
1631
1636
  }
1632
1637
 
@@ -1702,13 +1707,13 @@ class Directive {
1702
1707
  sourceFile,
1703
1708
  namespace: { start: comment.pos, end: comment.pos + namespaceText.length, text: namespaceText },
1704
1709
  };
1705
- const directiveSeparatorText = match?.[2];
1706
- const directiveText = match?.[3];
1710
+ const directiveSeparatorText = match[2];
1711
+ const directiveText = match[3];
1707
1712
  if (typeof directiveText === "string" && typeof directiveSeparatorText === "string") {
1708
1713
  const start = range.namespace.end + directiveSeparatorText.length;
1709
1714
  range.directive = { start, end: start + directiveText.length, text: directiveText };
1710
- const argumentSeparatorText = match?.[4];
1711
- const argumentText = match?.[5]?.trimEnd();
1715
+ const argumentSeparatorText = match[4];
1716
+ const argumentText = match[5]?.trimEnd();
1712
1717
  if (typeof argumentSeparatorText === "string" && typeof argumentText === "string") {
1713
1718
  const start = range.directive.end + argumentSeparatorText.length;
1714
1719
  range.argument = { start, end: start + argumentText.length, text: argumentText };
@@ -1740,10 +1745,10 @@ class Directive {
1740
1745
  const origin = new DiagnosticOrigin(range.argument.start, range.argument.end, range.sourceFile);
1741
1746
  Directive.#onDiagnostics(Diagnostic.error(text, origin));
1742
1747
  }
1743
- inlineConfig[range.directive?.text] = true;
1748
+ inlineConfig[range.directive.text] = true;
1744
1749
  return;
1745
1750
  }
1746
- const target = range?.directive ?? range.namespace;
1751
+ const target = range.directive ?? range.namespace;
1747
1752
  const text = DirectiveDiagnosticText.isNotSupported(target.text);
1748
1753
  const origin = new DiagnosticOrigin(target.start, target.end, range.sourceFile);
1749
1754
  Directive.#onDiagnostics(Diagnostic.error(text, origin));
@@ -1867,13 +1872,21 @@ class FileResult {
1867
1872
  }
1868
1873
  }
1869
1874
 
1875
+ var ProjectConfigKind;
1876
+ (function (ProjectConfigKind) {
1877
+ ProjectConfigKind[ProjectConfigKind["Discovered"] = 0] = "Discovered";
1878
+ ProjectConfigKind[ProjectConfigKind["Default"] = 1] = "Default";
1879
+ ProjectConfigKind[ProjectConfigKind["Provided"] = 2] = "Provided";
1880
+ ProjectConfigKind[ProjectConfigKind["Synthetic"] = 3] = "Synthetic";
1881
+ })(ProjectConfigKind || (ProjectConfigKind = {}));
1882
+
1870
1883
  class ProjectResult {
1871
1884
  compilerVersion;
1872
- projectConfigFilePath;
1885
+ projectConfig;
1873
1886
  results = [];
1874
- constructor(compilerVersion, projectConfigFilePath) {
1887
+ constructor(compilerVersion, projectConfig) {
1875
1888
  this.compilerVersion = compilerVersion;
1876
- this.projectConfigFilePath = projectConfigFilePath;
1889
+ this.projectConfig = projectConfig;
1877
1890
  }
1878
1891
  }
1879
1892
 
@@ -1975,10 +1988,10 @@ class ResultHandler {
1975
1988
  }
1976
1989
  break;
1977
1990
  case "project:uses": {
1978
- let projectResult = this.#targetResult.results.get(payload.projectConfigFilePath);
1991
+ let projectResult = this.#targetResult.results.get(payload.projectConfig.specifier);
1979
1992
  if (!projectResult) {
1980
- projectResult = new ProjectResult(payload.compilerVersion, payload.projectConfigFilePath);
1981
- this.#targetResult.results.set(payload.projectConfigFilePath, projectResult);
1993
+ projectResult = new ProjectResult(payload.compilerVersion, payload.projectConfig);
1994
+ this.#targetResult.results.set(payload.projectConfig.specifier, projectResult);
1982
1995
  }
1983
1996
  this.#projectResult = projectResult;
1984
1997
  break;
@@ -2222,7 +2235,10 @@ class Scribbler {
2222
2235
  }
2223
2236
  }
2224
2237
 
2225
- function addsPackageText(packageVersion, packagePath) {
2238
+ function addsText(packageVersion, packagePath, options) {
2239
+ if (options?.short) {
2240
+ return (jsx(Line, { children: jsx(Text, { color: "90", children: packageVersion }) }));
2241
+ }
2226
2242
  return (jsx(Line, { children: [jsx(Text, { color: "90", children: "adds" }), " TypeScript ", packageVersion, jsx(Text, { color: "90", children: [" to ", packagePath] })] }));
2227
2243
  }
2228
2244
 
@@ -2319,6 +2335,16 @@ function diagnosticText(diagnostic, codeFrameOptions = {}) {
2319
2335
  return (jsx(Text, { children: [prefix, jsx(DiagnosticText, { codeFrameOptions: codeFrameOptions, diagnostic: diagnostic })] }));
2320
2336
  }
2321
2337
 
2338
+ function dotText(status) {
2339
+ let statusColor;
2340
+ let statusText = "·";
2341
+ if (status === "failed") {
2342
+ statusColor = "31";
2343
+ statusText = "×";
2344
+ }
2345
+ return jsx(Text, { color: statusColor, children: statusText });
2346
+ }
2347
+
2322
2348
  function getStatusColor(status) {
2323
2349
  switch (status) {
2324
2350
  case "runs":
@@ -2366,10 +2392,6 @@ function fileStatusText(status, file) {
2366
2392
  return (jsx(Line, { children: [jsx(Text, { color: getStatusColor(status), children: statusText }), " ", jsx(FileNameText, { filePath: file.path })] }));
2367
2393
  }
2368
2394
 
2369
- function fileViewText(lines, addEmptyFinalLine) {
2370
- return (jsx(Text, { children: [[...lines], addEmptyFinalLine ? jsx(Line, {}) : undefined] }));
2371
- }
2372
-
2373
2395
  function formattedText(input) {
2374
2396
  if (typeof input === "string") {
2375
2397
  return jsx(Line, { children: input });
@@ -2460,7 +2482,8 @@ class OutputService {
2460
2482
  static errorStream = new StreamController(process.stderr);
2461
2483
  static outputStream = new StreamController(process.stdout);
2462
2484
  static #isClear = false;
2463
- static #scribbler = new Scribbler();
2485
+ static #newLine = "\n";
2486
+ static #scribbler = new Scribbler({ newLine: OutputService.#newLine });
2464
2487
  static clearTerminal() {
2465
2488
  if (!OutputService.#isClear) {
2466
2489
  OutputService.outputStream.write("\u001B[2J\u001B[3J\u001B[H");
@@ -2470,21 +2493,24 @@ class OutputService {
2470
2493
  static eraseLastLine() {
2471
2494
  OutputService.outputStream.write("\u001B[1A\u001B[0K");
2472
2495
  }
2473
- static #writeTo(stream, element) {
2496
+ static #write(stream, element) {
2474
2497
  const elements = Array.isArray(element) ? element : [element];
2475
2498
  for (const element of elements) {
2476
2499
  stream.write(OutputService.#scribbler.render(element));
2477
2500
  }
2478
2501
  OutputService.#isClear = false;
2479
2502
  }
2503
+ static writeBlankLine(count = 1) {
2504
+ OutputService.outputStream.write(OutputService.#newLine.repeat(count));
2505
+ }
2480
2506
  static writeError(element) {
2481
- OutputService.#writeTo(OutputService.errorStream, element);
2507
+ OutputService.#write(OutputService.errorStream, element);
2482
2508
  }
2483
2509
  static writeMessage(element) {
2484
- OutputService.#writeTo(OutputService.outputStream, element);
2510
+ OutputService.#write(OutputService.outputStream, element);
2485
2511
  }
2486
2512
  static writeWarning(element) {
2487
- OutputService.#writeTo(OutputService.errorStream, element);
2513
+ OutputService.#write(OutputService.errorStream, element);
2488
2514
  }
2489
2515
  }
2490
2516
 
@@ -2543,12 +2569,24 @@ function testNameText(status, name, indent = 0) {
2543
2569
  return (jsx(Line, { indent: indent + 1, children: [jsx(Text, { color: getStatusColor(status), children: statusText }), " ", jsx(Text, { color: "90", children: name })] }));
2544
2570
  }
2545
2571
 
2546
- function usesCompilerText(compilerVersion, projectConfigFilePath, options) {
2547
- let projectConfigPathText;
2548
- if (projectConfigFilePath != null) {
2549
- projectConfigPathText = (jsx(Text, { color: "90", children: [" with ", Path.relative("", projectConfigFilePath)] }));
2572
+ function usesText(compilerVersion, projectConfig, options) {
2573
+ if (options?.short) {
2574
+ return jsx(Text, { color: "34", children: compilerVersion });
2550
2575
  }
2551
- return (jsx(Text, { children: [options?.prependEmptyLine ? jsx(Line, {}) : undefined, jsx(Line, { children: [jsx(Text, { color: "34", children: "uses" }), " TypeScript ", compilerVersion, projectConfigPathText] }), jsx(Line, {})] }));
2576
+ let projectConfigText;
2577
+ switch (projectConfig.kind) {
2578
+ case 0:
2579
+ case 2:
2580
+ projectConfigText = (jsx(Text, { color: "90", children: [" with ", Path.relative("", projectConfig.specifier)] }));
2581
+ break;
2582
+ case 1:
2583
+ projectConfigText = (jsx(Text, { color: "90", children: [" with ", projectConfig.specifier, " TSConfig"] }));
2584
+ break;
2585
+ case 3:
2586
+ projectConfigText = jsx(Text, { color: "90", children: " with inline TSConfig" });
2587
+ break;
2588
+ }
2589
+ return (jsx(Text, { children: [jsx(Line, { children: [jsx(Text, { color: "34", children: "uses" }), " TypeScript ", compilerVersion, projectConfigText] }), jsx(Line, {})] }));
2552
2590
  }
2553
2591
 
2554
2592
  function waitingForFileChangesText() {
@@ -2573,6 +2611,55 @@ class BaseReporter {
2573
2611
  }
2574
2612
  }
2575
2613
 
2614
+ class DotReporter extends BaseReporter {
2615
+ #diagnostics = [];
2616
+ #hasReportedAdds = false;
2617
+ on([event, payload]) {
2618
+ switch (event) {
2619
+ case "store:adds":
2620
+ OutputService.writeMessage(addsText(payload.packageVersion, payload.packagePath, { short: true }));
2621
+ this.#hasReportedAdds = true;
2622
+ break;
2623
+ case "store:error":
2624
+ for (const diagnostic of payload.diagnostics) {
2625
+ OutputService.writeError(diagnosticText(diagnostic));
2626
+ }
2627
+ break;
2628
+ case "project:uses":
2629
+ if (this.#hasReportedAdds) {
2630
+ if (!environmentOptions.noInteractive) {
2631
+ OutputService.eraseLastLine();
2632
+ }
2633
+ this.#hasReportedAdds = false;
2634
+ }
2635
+ if (this.resolvedConfig.target.length > 1) {
2636
+ OutputService.writeMessage(usesText(payload.compilerVersion, payload.projectConfig, { short: true }));
2637
+ }
2638
+ break;
2639
+ case "target:end":
2640
+ OutputService.writeBlankLine(2);
2641
+ for (const diagnostic of this.#diagnostics) {
2642
+ OutputService.writeError(diagnosticText(diagnostic));
2643
+ }
2644
+ this.#diagnostics = [];
2645
+ break;
2646
+ case "file:end":
2647
+ OutputService.writeMessage(dotText(payload.result.status));
2648
+ break;
2649
+ case "project:error":
2650
+ case "file:error":
2651
+ case "directive:error":
2652
+ case "collect:error":
2653
+ case "test:error":
2654
+ case "suppressed:error":
2655
+ case "expect:error":
2656
+ case "expect:fail":
2657
+ this.#diagnostics.push(...payload.diagnostics);
2658
+ break;
2659
+ }
2660
+ }
2661
+ }
2662
+
2576
2663
  class FileView {
2577
2664
  #indent = 0;
2578
2665
  #lines = [];
@@ -2598,8 +2685,8 @@ class FileView {
2598
2685
  getMessages() {
2599
2686
  return this.#messages;
2600
2687
  }
2601
- getViewText(options) {
2602
- return fileViewText(this.#lines, options?.appendEmptyLine || this.hasErrors());
2688
+ getView() {
2689
+ return this.#lines;
2603
2690
  }
2604
2691
  hasErrors() {
2605
2692
  return this.#messages.length > 0;
@@ -2612,17 +2699,15 @@ class ListReporter extends BaseReporter {
2612
2699
  #hasReportedAdds = false;
2613
2700
  #hasReportedError = false;
2614
2701
  #hasReportedUses = false;
2615
- #isFileViewExpanded = false;
2616
- #isLastFile() {
2617
- return this.#fileCount === 0;
2618
- }
2702
+ #isVerbose = false;
2619
2703
  on([event, payload]) {
2620
2704
  switch (event) {
2621
2705
  case "run:start":
2622
- this.#isFileViewExpanded = payload.result.files.length === 1 && this.resolvedConfig.watch !== true;
2706
+ this.#isVerbose =
2707
+ this.resolvedConfig.verbose || (payload.result.files.length === 1 && this.resolvedConfig.watch !== true);
2623
2708
  break;
2624
2709
  case "store:adds":
2625
- OutputService.writeMessage(addsPackageText(payload.packageVersion, payload.packagePath));
2710
+ OutputService.writeMessage(addsText(payload.packageVersion, payload.packagePath));
2626
2711
  this.#hasReportedAdds = true;
2627
2712
  break;
2628
2713
  case "store:error":
@@ -2635,9 +2720,10 @@ class ListReporter extends BaseReporter {
2635
2720
  this.#hasReportedUses = false;
2636
2721
  break;
2637
2722
  case "project:uses":
2638
- OutputService.writeMessage(usesCompilerText(payload.compilerVersion, payload.projectConfigFilePath, {
2639
- prependEmptyLine: this.#hasReportedUses && !this.#hasReportedAdds && !this.#hasReportedError,
2640
- }));
2723
+ if (this.#hasReportedUses && !(this.#hasReportedAdds || this.#hasReportedError)) {
2724
+ OutputService.writeBlankLine();
2725
+ }
2726
+ OutputService.writeMessage(usesText(payload.compilerVersion, payload.projectConfig));
2641
2727
  this.#hasReportedAdds = false;
2642
2728
  this.#hasReportedUses = true;
2643
2729
  break;
@@ -2666,7 +2752,10 @@ class ListReporter extends BaseReporter {
2666
2752
  OutputService.eraseLastLine();
2667
2753
  }
2668
2754
  OutputService.writeMessage(fileStatusText(payload.result.status, payload.result.file));
2669
- OutputService.writeMessage(this.#fileView.getViewText({ appendEmptyLine: this.#isLastFile() }));
2755
+ OutputService.writeMessage(this.#fileView.getView());
2756
+ if (this.#isVerbose || this.#fileCount === 0 || this.#fileView.hasErrors()) {
2757
+ OutputService.writeBlankLine();
2758
+ }
2670
2759
  if (this.#fileView.hasErrors()) {
2671
2760
  OutputService.writeError(this.#fileView.getMessages());
2672
2761
  this.#hasReportedError = true;
@@ -2674,32 +2763,32 @@ class ListReporter extends BaseReporter {
2674
2763
  this.#fileView.clear();
2675
2764
  break;
2676
2765
  case "describe:start":
2677
- if (this.#isFileViewExpanded) {
2766
+ if (this.#isVerbose) {
2678
2767
  this.#fileView.beginDescribe(payload.result.describe.name);
2679
2768
  }
2680
2769
  break;
2681
2770
  case "describe:end":
2682
- if (this.#isFileViewExpanded) {
2771
+ if (this.#isVerbose) {
2683
2772
  this.#fileView.endDescribe();
2684
2773
  }
2685
2774
  break;
2686
2775
  case "test:skip":
2687
- if (this.#isFileViewExpanded) {
2776
+ if (this.#isVerbose) {
2688
2777
  this.#fileView.addTest("skipped", payload.result.test.name);
2689
2778
  }
2690
2779
  break;
2691
2780
  case "test:fixme":
2692
- if (this.#isFileViewExpanded) {
2781
+ if (this.#isVerbose) {
2693
2782
  this.#fileView.addTest("fixme", payload.result.test.name);
2694
2783
  }
2695
2784
  break;
2696
2785
  case "test:todo":
2697
- if (this.#isFileViewExpanded) {
2786
+ if (this.#isVerbose) {
2698
2787
  this.#fileView.addTest("todo", payload.result.test.name);
2699
2788
  }
2700
2789
  break;
2701
2790
  case "test:error":
2702
- if (this.#isFileViewExpanded) {
2791
+ if (this.#isVerbose) {
2703
2792
  this.#fileView.addTest("failed", payload.result.test.name);
2704
2793
  }
2705
2794
  for (const diagnostic of payload.diagnostics) {
@@ -2707,12 +2796,12 @@ class ListReporter extends BaseReporter {
2707
2796
  }
2708
2797
  break;
2709
2798
  case "test:fail":
2710
- if (this.#isFileViewExpanded) {
2799
+ if (this.#isVerbose) {
2711
2800
  this.#fileView.addTest("failed", payload.result.test.name);
2712
2801
  }
2713
2802
  break;
2714
2803
  case "test:pass":
2715
- if (this.#isFileViewExpanded) {
2804
+ if (this.#isVerbose) {
2716
2805
  this.#fileView.addTest("passed", payload.result.test.name);
2717
2806
  }
2718
2807
  break;
@@ -2729,7 +2818,7 @@ class ListReporter extends BaseReporter {
2729
2818
  class SetupReporter {
2730
2819
  on([event, payload]) {
2731
2820
  if (event === "store:adds") {
2732
- OutputService.writeMessage(addsPackageText(payload.packageVersion, payload.packagePath));
2821
+ OutputService.writeMessage(addsText(payload.packageVersion, payload.packagePath));
2733
2822
  return;
2734
2823
  }
2735
2824
  if ("diagnostics" in payload) {
@@ -2995,7 +3084,7 @@ class Glob {
2995
3084
  class SelectDiagnosticText {
2996
3085
  static #pathSelectOptions(resolvedConfig) {
2997
3086
  const text = [
2998
- `Root path: ${resolvedConfig.rootPath}`,
3087
+ `Root directory: ${resolvedConfig.rootPath}`,
2999
3088
  `Test file match: ${resolvedConfig.testFileMatch.join(", ")}`,
3000
3089
  ];
3001
3090
  if (resolvedConfig.pathMatch.length > 0) {
@@ -3489,11 +3578,11 @@ class SuppressedLayer {
3489
3578
  #collectSuppressedErrors(text) {
3490
3579
  const ranges = [];
3491
3580
  for (const match of text.matchAll(this.#expectErrorRegex)) {
3492
- const offsetText = match?.[1];
3493
- const directiveText = match?.[2];
3494
- const ignoreText = match?.[3];
3495
- const argumentSeparatorText = match?.[4];
3496
- const argumentText = match?.[5]?.split(/--+/)[0]?.trimEnd();
3581
+ const offsetText = match[1];
3582
+ const directiveText = match[2];
3583
+ const ignoreText = match[3];
3584
+ const argumentSeparatorText = match[4];
3585
+ const argumentText = match[5]?.split(/--+/)[0]?.trimEnd();
3497
3586
  if (typeof offsetText !== "string" || !directiveText) {
3498
3587
  continue;
3499
3588
  }
@@ -3978,7 +4067,9 @@ var TestTreeNodeFlags;
3978
4067
 
3979
4068
  class ProjectService {
3980
4069
  #compiler;
4070
+ #host;
3981
4071
  #lastSeenProject = "";
4072
+ #projectConfig;
3982
4073
  #resolvedConfig;
3983
4074
  #seenPrograms = new WeakSet();
3984
4075
  #seenTestFiles = new Set();
@@ -3986,6 +4077,7 @@ class ProjectService {
3986
4077
  constructor(compiler, resolvedConfig) {
3987
4078
  this.#compiler = compiler;
3988
4079
  this.#resolvedConfig = resolvedConfig;
4080
+ this.#projectConfig = this.#resolveProjectConfig(resolvedConfig.tsconfig);
3989
4081
  const noop = () => undefined;
3990
4082
  const noopLogger = {
3991
4083
  close: noop,
@@ -4001,8 +4093,8 @@ class ProjectService {
4001
4093
  const noopWatcher = {
4002
4094
  close: noop,
4003
4095
  };
4004
- const host = {
4005
- ...this.#compiler.sys,
4096
+ this.#host = {
4097
+ ...compiler.sys,
4006
4098
  clearImmediate,
4007
4099
  clearTimeout,
4008
4100
  setImmediate,
@@ -4010,10 +4102,13 @@ class ProjectService {
4010
4102
  watchDirectory: () => noopWatcher,
4011
4103
  watchFile: () => noopWatcher,
4012
4104
  };
4105
+ if (this.#projectConfig.kind === 3) {
4106
+ this.#host.readFile = (path) => path === this.#projectConfig.specifier ? resolvedConfig.tsconfig : compiler.sys.readFile(path);
4107
+ }
4013
4108
  this.#service = new this.#compiler.server.ProjectService({
4014
4109
  allowLocalPluginLoads: true,
4015
4110
  cancellationToken: this.#compiler.server.nullCancellationToken,
4016
- host,
4111
+ host: this.#host,
4017
4112
  logger: noopLogger,
4018
4113
  session: undefined,
4019
4114
  useInferredProjectPerProjectRoot: true,
@@ -4067,29 +4162,44 @@ class ProjectService {
4067
4162
  return project?.getLanguageService(true);
4068
4163
  }
4069
4164
  #isFileIncluded(filePath) {
4070
- const configSourceFile = this.#compiler.readJsonConfigFile(this.#resolvedConfig.tsconfig, this.#compiler.sys.readFile);
4071
- const { fileNames } = this.#compiler.parseJsonSourceFileConfigFileContent(configSourceFile, this.#compiler.sys, Path.dirname(this.#resolvedConfig.tsconfig), undefined, this.#resolvedConfig.tsconfig);
4165
+ const configSourceFile = this.#compiler.readJsonConfigFile(this.#projectConfig.specifier, this.#host.readFile);
4166
+ const { fileNames } = this.#compiler.parseJsonSourceFileConfigFileContent(configSourceFile, this.#host, Path.dirname(this.#projectConfig.specifier), undefined, this.#projectConfig.specifier);
4072
4167
  return fileNames.includes(filePath);
4073
4168
  }
4169
+ #resolveProjectConfig(specifier) {
4170
+ if (specifier === "baseline") {
4171
+ return { kind: 1, specifier: "baseline" };
4172
+ }
4173
+ if (specifier === "findup") {
4174
+ return { kind: 0, specifier: "" };
4175
+ }
4176
+ if (Options.isJsonString(specifier)) {
4177
+ return {
4178
+ kind: 3,
4179
+ specifier: Path.resolve(this.#resolvedConfig.rootPath, `${Math.random().toString(32).slice(2)}.tsconfig.json`),
4180
+ };
4181
+ }
4182
+ return { kind: 2, specifier };
4183
+ }
4074
4184
  openFile(filePath, sourceText) {
4075
- switch (this.#resolvedConfig.tsconfig) {
4076
- case "findup":
4185
+ switch (this.#projectConfig.kind) {
4186
+ case 0:
4077
4187
  break;
4078
- case "ignore":
4188
+ case 1:
4079
4189
  this.#service.getConfigFileNameForFile = () => undefined;
4080
4190
  break;
4081
4191
  default:
4082
4192
  this.#service.getConfigFileNameForFile = this.#isFileIncluded(filePath)
4083
- ? () => this.#resolvedConfig.tsconfig
4193
+ ? () => this.#projectConfig.specifier
4084
4194
  : () => undefined;
4085
4195
  }
4086
4196
  const { configFileErrors, configFileName } = this.#service.openClientFile(filePath, sourceText, undefined, this.#resolvedConfig.rootPath);
4087
4197
  if (configFileName !== this.#lastSeenProject) {
4088
4198
  this.#lastSeenProject = configFileName;
4089
- EventEmitter.dispatch([
4090
- "project:uses",
4091
- { compilerVersion: this.#compiler.version, projectConfigFilePath: configFileName },
4092
- ]);
4199
+ const projectConfig = configFileName != null
4200
+ ? { ...this.#projectConfig, specifier: configFileName }
4201
+ : { kind: 1, specifier: "baseline" };
4202
+ EventEmitter.dispatch(["project:uses", { compilerVersion: this.#compiler.version, projectConfig }]);
4093
4203
  if (configFileErrors && configFileErrors.length > 0) {
4094
4204
  EventEmitter.dispatch([
4095
4205
  "project:error",
@@ -5484,7 +5594,7 @@ class ExpectService {
5484
5594
  return;
5485
5595
  }
5486
5596
  const matchWorker = new MatchWorker(this.#compiler, this.#program, assertionNode);
5487
- if (!(matcherNameText === "toRaiseError" && assertionNode.isNot === false) &&
5597
+ if (!(matcherNameText === "toRaiseError" && !assertionNode.isNot) &&
5488
5598
  this.#reject.argumentType([
5489
5599
  ["source", assertionNode.source[0]],
5490
5600
  ["target", assertionNode.target?.[0]],
@@ -5550,10 +5660,10 @@ class Reject {
5550
5660
  constructor(compiler, program, resolvedConfig) {
5551
5661
  this.#compiler = compiler;
5552
5662
  this.#typeChecker = program.getTypeChecker();
5553
- if (resolvedConfig?.rejectAnyType) {
5663
+ if (resolvedConfig.rejectAnyType) {
5554
5664
  this.#rejectedArgumentTypes.add("any");
5555
5665
  }
5556
- if (resolvedConfig?.rejectNeverType) {
5666
+ if (resolvedConfig.rejectNeverType) {
5557
5667
  this.#rejectedArgumentTypes.add("never");
5558
5668
  }
5559
5669
  }
@@ -5683,11 +5793,11 @@ class FixmeService {
5683
5793
  let isFail;
5684
5794
  if (owner === FixmeService.#expectRange?.owner) {
5685
5795
  isFail = FixmeService.#expectRange.isFail;
5686
- FixmeService.#expectRange = FixmeService.#expectRange?.previous;
5796
+ FixmeService.#expectRange = FixmeService.#expectRange.previous;
5687
5797
  }
5688
5798
  if (owner === FixmeService.#range?.owner) {
5689
- isFail = FixmeService.#range?.isFail;
5690
- FixmeService.#range = FixmeService.#range?.previous;
5799
+ isFail = FixmeService.#range.isFail;
5800
+ FixmeService.#range = FixmeService.#range.previous;
5691
5801
  }
5692
5802
  if (isFail === false) {
5693
5803
  const text = [FixmeDiagnosticText.wasSupposedToFail(owner.brand), FixmeDiagnosticText.considerRemoving()];
@@ -5955,7 +6065,7 @@ class FileRunner {
5955
6065
  class Runner {
5956
6066
  #eventEmitter = new EventEmitter();
5957
6067
  #resolvedConfig;
5958
- static version = "6.1.0";
6068
+ static version = "7.0.0-beta.0";
5959
6069
  constructor(resolvedConfig) {
5960
6070
  this.#resolvedConfig = resolvedConfig;
5961
6071
  }
@@ -5974,14 +6084,16 @@ class Runner {
5974
6084
  }
5975
6085
  for (const reporter of this.#resolvedConfig.reporters) {
5976
6086
  switch (reporter) {
6087
+ case "dot": {
6088
+ this.#eventEmitter.addReporter(new DotReporter(this.#resolvedConfig));
6089
+ break;
6090
+ }
5977
6091
  case "list": {
5978
- const listReporter = new ListReporter(this.#resolvedConfig);
5979
- this.#eventEmitter.addReporter(listReporter);
6092
+ this.#eventEmitter.addReporter(new ListReporter(this.#resolvedConfig));
5980
6093
  break;
5981
6094
  }
5982
6095
  case "summary": {
5983
- const summaryReporter = new SummaryReporter(this.#resolvedConfig);
5984
- this.#eventEmitter.addReporter(summaryReporter);
6096
+ this.#eventEmitter.addReporter(new SummaryReporter(this.#resolvedConfig));
5985
6097
  break;
5986
6098
  }
5987
6099
  default: {
@@ -6040,7 +6152,17 @@ class Runner {
6040
6152
  }
6041
6153
  }
6042
6154
 
6155
+ class CliDiagnosticText {
6156
+ static configLocationChanged(oldConfigFilePath, newConfigFilePath) {
6157
+ return [
6158
+ "The default configuration file location has changed.",
6159
+ `The discovered file has been automatically renamed from '${Path.relative(".", oldConfigFilePath)}' to '${Path.relative(".", newConfigFilePath)}'.`,
6160
+ ];
6161
+ }
6162
+ }
6163
+
6043
6164
  class Cli {
6165
+ #deferredDiagnostics;
6044
6166
  #eventEmitter = new EventEmitter();
6045
6167
  #noErrorExitCode;
6046
6168
  constructor(options) {
@@ -6081,6 +6203,14 @@ class Cli {
6081
6203
  if (cancellationToken.isCancellationRequested()) {
6082
6204
  return;
6083
6205
  }
6206
+ if (!commandLineOptions.config) {
6207
+ const oldConfigFilePath = Path.resolve(Config.resolveRootPath(commandLineOptions.root), "./tstyche.config.json");
6208
+ if (existsSync(oldConfigFilePath) && !environmentOptions.isCi) {
6209
+ const newConfigFilePath = Path.resolve(Config.resolveConfigFilePath(undefined, commandLineOptions.root));
6210
+ await fs.rename(oldConfigFilePath, newConfigFilePath);
6211
+ this.#deferredDiagnostics = Diagnostic.warning(CliDiagnosticText.configLocationChanged(oldConfigFilePath, newConfigFilePath));
6212
+ }
6213
+ }
6084
6214
  do {
6085
6215
  if (cancellationToken.getReason() === "configChange") {
6086
6216
  cancellationToken.reset();
@@ -6089,13 +6219,8 @@ class Cli {
6089
6219
  this.#eventEmitter.addHandler(cancellationHandler);
6090
6220
  this.#eventEmitter.addReporter(setupReporter);
6091
6221
  }
6092
- const { configFileOptions, configFilePath } = await Config.parseConfigFile(commandLineOptions.config, commandLineOptions.root);
6093
- const resolvedConfig = Config.resolve({
6094
- configFileOptions,
6095
- configFilePath,
6096
- commandLineOptions,
6097
- pathMatch,
6098
- });
6222
+ const { configFileOptions } = await Config.parseConfigFile(commandLineOptions.config, commandLineOptions.root);
6223
+ const resolvedConfig = Config.resolve({ configFileOptions, commandLineOptions, pathMatch });
6099
6224
  if (cancellationToken.isCancellationRequested()) {
6100
6225
  if (commandLine.includes("--watch")) {
6101
6226
  await this.#waitForChangedFiles(resolvedConfig, cancellationToken);
@@ -6123,7 +6248,7 @@ class Cli {
6123
6248
  }
6124
6249
  }
6125
6250
  if (commandLine.includes("--listFiles")) {
6126
- OutputService.writeMessage(formattedText(testFiles.map((testFile) => testFile.toString())));
6251
+ OutputService.writeMessage(formattedText(testFiles));
6127
6252
  continue;
6128
6253
  }
6129
6254
  this.#eventEmitter.removeHandler(cancellationHandler);
@@ -6131,6 +6256,10 @@ class Cli {
6131
6256
  const runner = new Runner(resolvedConfig);
6132
6257
  await runner.run(testFiles, cancellationToken);
6133
6258
  } while (cancellationToken.getReason() === "configChange");
6259
+ if (this.#deferredDiagnostics != null) {
6260
+ OutputService.writeBlankLine();
6261
+ OutputService.writeWarning(diagnosticText(this.#deferredDiagnostics));
6262
+ }
6134
6263
  this.#eventEmitter.removeHandlers();
6135
6264
  }
6136
6265
  #waitForChangedFiles(resolvedConfig, cancellationToken) {
@@ -6161,4 +6290,4 @@ class Cli {
6161
6290
  }
6162
6291
  }
6163
6292
 
6164
- export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectResult, Result, ResultStatus, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, Store, StreamController, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
6293
+ export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, DotReporter, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectConfigKind, ProjectResult, Result, ResultStatus, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, Store, StreamController, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, dotText, environmentOptions, fileStatusText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesText, waitingForFileChangesText, watchUsageText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "6.1.0",
3
+ "version": "7.0.0-beta.0",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",