monocart-coverage-reports 2.13.2 → 3.1.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.
Files changed (69) hide show
  1. package/README.md +314 -116
  2. package/README.zh-Hans.md +315 -117
  3. package/lib/assets.js +6 -6
  4. package/lib/cli.js +191 -95
  5. package/lib/client/cdp-client.js +74 -43
  6. package/lib/client/coverage-client.js +24 -8
  7. package/lib/client/ws-session.js +115 -37
  8. package/lib/converter/ast-visitor.js +5 -7
  9. package/lib/converter/ast.js +29 -8
  10. package/lib/converter/collect-source-maps.js +42 -21
  11. package/lib/converter/converter.js +124 -129
  12. package/lib/converter/css-coverage.js +76 -0
  13. package/lib/converter/fake-source-coverage.js +64 -0
  14. package/lib/converter/find-original-range.js +214 -6
  15. package/lib/converter/flatten-source-maps.js +2 -4
  16. package/lib/converter/ignore.js +2 -4
  17. package/lib/converter/info-branch.js +5 -3
  18. package/lib/converter/info-function.js +5 -3
  19. package/lib/converter/info-statement.js +5 -3
  20. package/lib/converter/range-index.js +78 -0
  21. package/lib/converter/source-range-merge.js +103 -0
  22. package/lib/converter/untested.js +30 -60
  23. package/lib/default/options.js +13 -1
  24. package/lib/generate.js +44 -26
  25. package/lib/index.d.ts +52 -4
  26. package/lib/index.js +35 -41
  27. package/lib/istanbul/istanbul-summary.js +2 -2
  28. package/lib/istanbul/istanbul.js +35 -13
  29. package/lib/packages/monocart-coverage-assets.js +4 -3
  30. package/lib/packages/monocart-coverage-converter.js +27 -0
  31. package/lib/packages/monocart-coverage-vendor.js +2 -41
  32. package/lib/packages/monocart-coverage-vendor.js.LICENSE +3 -221
  33. package/lib/platform/concurrency.js +47 -43
  34. package/lib/platform/share.js +8 -1
  35. package/lib/register/hooks.js +19 -13
  36. package/lib/register/register.js +5 -3
  37. package/lib/reports/codacy.js +3 -5
  38. package/lib/reports/codecov.js +3 -5
  39. package/lib/reports/console-details.js +5 -5
  40. package/lib/reports/console-summary.js +4 -4
  41. package/lib/reports/custom.js +8 -24
  42. package/lib/reports/markdown-details.js +4 -6
  43. package/lib/reports/markdown-summary.js +4 -6
  44. package/lib/reports/raw.js +10 -12
  45. package/lib/reports/v8-json.js +3 -5
  46. package/lib/reports/v8.js +3 -5
  47. package/lib/utils/dedupe.js +1 -1
  48. package/lib/utils/gc.js +30 -14
  49. package/lib/utils/markdown.js +2 -2
  50. package/lib/utils/merge/merge.js +2 -4
  51. package/lib/utils/merge/range-tree.js +1 -1
  52. package/lib/utils/request.js +85 -73
  53. package/lib/utils/snapshot.js +4 -4
  54. package/lib/utils/source-path.js +26 -11
  55. package/lib/utils/util.js +67 -42
  56. package/lib/v8/v8-summary.js +2 -4
  57. package/lib/v8/v8.js +11 -11
  58. package/migrate-to-3.md +175 -0
  59. package/package.json +54 -42
  60. package/skills/monocart-coverage-reports/SKILL.md +106 -0
  61. package/skills/monocart-coverage-reports/references/best-practices.md +218 -0
  62. package/skills/monocart-coverage-reports/references/cli.md +108 -0
  63. package/skills/monocart-coverage-reports/references/collection.md +154 -0
  64. package/skills/monocart-coverage-reports/references/filtering-and-sourcemaps.md +170 -0
  65. package/skills/monocart-coverage-reports/references/reports-and-ci.md +219 -0
  66. package/skills/monocart-coverage-reports/references/repository-map.md +59 -0
  67. package/lib/index.mjs +0 -9
  68. package/lib/register/hooks.mjs +0 -3
  69. package/lib/register/register.mjs +0 -3
@@ -1,4 +1,4 @@
1
- module.exports = {
1
+ const defaultOptions = {
2
2
 
3
3
  // {string} logging levels: off, error, info, debug
4
4
  logging: 'info',
@@ -24,6 +24,12 @@ module.exports = {
24
24
  // {string|string[]} input raw dir(s)
25
25
  inputDir: null,
26
26
 
27
+ // (mcr test only) {string|string[]|null} Test file paths or glob patterns accepted by node --test.
28
+ // A string is one positional argument; an array supplies multiple arguments unchanged.
29
+ // Used when no CLI targets are supplied; null skips tests and is not passed to Node.
30
+ // Ignored by other CLI commands and the API.
31
+ test: null,
32
+
27
33
  // {string} base dir for normalizing the relative source path, defaults to cwd
28
34
  baseDir: null,
29
35
 
@@ -43,6 +49,10 @@ module.exports = {
43
49
  // sourceFilter: (sourcePath) => sourcePath.search(/src\/.+/) !== -1,
44
50
  sourceFilter: null,
45
51
 
52
+ // (V8 only) Filter final files by sourcePath after sourcemap conversion and adding untested files.
53
+ // outputFilter: (entry) => entry.sourcePath.startsWith('src/'),
54
+ outputFilter: null,
55
+
46
56
  // The combined filter for entryFilter and sourceFilter
47
57
  filter: null,
48
58
 
@@ -105,3 +115,5 @@ module.exports = {
105
115
  // onEnd: async (reportData) => {}
106
116
  onEnd: null
107
117
  };
118
+
119
+ export { defaultOptions };
package/lib/generate.js CHANGED
@@ -1,35 +1,28 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { fileURLToPath } = require('url');
4
- const EC = require('eight-colors');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import EC from 'eight-colors';
5
5
 
6
- const Util = require('./utils/util.js');
7
- const { convertV8List } = require('./converter/converter.js');
8
- const { resolveSourceMap } = require('./converter/collect-source-maps.js');
9
- const { StreamZip } = require('./packages/monocart-coverage-vendor.js');
6
+ import { Util } from './utils/util.js';
7
+ import { resolveSourceMap } from './converter/collect-source-maps.js';
10
8
 
11
9
  // ========================================================================================================
12
10
  // built-in reports
13
11
 
14
- // istanbul
15
- const { mergeIstanbulCoverage, saveIstanbulReports } = require('./istanbul/istanbul.js');
16
-
17
12
  // v8
18
- const { mergeV8Coverage, saveV8Report } = require('./v8/v8.js');
13
+ import { mergeV8Coverage, saveV8Report } from './v8/v8.js';
19
14
 
20
15
  // both
21
- const { codecovReport } = require('./reports/codecov.js');
22
- const { codacyReport } = require('./reports/codacy.js');
23
-
24
- const { consoleDetailsReport } = require('./reports/console-details.js');
25
- const { consoleSummaryReport } = require('./reports/console-summary.js');
16
+ import { codecovReport } from './reports/codecov.js';
17
+ import { codacyReport } from './reports/codacy.js';
26
18
 
27
- const { markdownDetailsReport } = require('./reports/markdown-details.js');
28
- const { markdownSummaryReport } = require('./reports/markdown-summary.js');
19
+ import { consoleDetailsReport } from './reports/console-details.js';
20
+ import { consoleSummaryReport } from './reports/console-summary.js';
29
21
 
30
- const { rawReport } = require('./reports/raw.js');
22
+ import { markdownDetailsReport } from './reports/markdown-details.js';
23
+ import { markdownSummaryReport } from './reports/markdown-summary.js';
31
24
 
32
- const { customReport } = require('./reports/custom.js');
25
+ import { customReport } from './reports/custom.js';
33
26
 
34
27
  const allBuiltInReports = {
35
28
  // v8
@@ -71,7 +64,10 @@ const bothBuiltInReports = {
71
64
  'markdown-details': markdownDetailsReport,
72
65
  'markdown-summary': markdownSummaryReport,
73
66
 
74
- 'raw': rawReport
67
+ 'raw': async (... args) => {
68
+ const { rawReport } = await import('./reports/raw.js');
69
+ return rawReport(... args);
70
+ }
75
71
  };
76
72
 
77
73
  // ========================================================================================================
@@ -146,6 +142,7 @@ const generateV8ListReports = async (v8list, coverageData, fileSources, options)
146
142
  let istanbulReportPath;
147
143
  // v8 to istanbul reports
148
144
  if (options.reportGroup.has('istanbul')) {
145
+ const { saveIstanbulReports } = await import('./istanbul/istanbul.js');
149
146
  const istanbulCoverageResults = await saveIstanbulReports(coverageData, fileSources, options);
150
147
  istanbulReportPath = istanbulCoverageResults.reportPath;
151
148
  }
@@ -175,17 +172,34 @@ const getCoverageResults = async (dataList, sourceCache, options) => {
175
172
  // console.log('after merge', v8list.map((it) => it.url));
176
173
 
177
174
  const t2 = Date.now();
178
- const results = await convertV8List(v8list, options);
175
+ const { convertV8List } = await import('./converter/converter.js');
176
+ const results = await convertV8List(v8list, options, options.reportGroup.has('istanbul'));
179
177
  Util.logTime(`${EC.magenta('├')} [generate] converted coverage data`, t2);
180
178
 
181
179
  const {
182
180
  v8DataList, coverageData, fileSources
183
181
  } = results;
184
- return generateV8ListReports(v8DataList, coverageData, fileSources, options);
182
+
183
+ let filteredV8DataList = v8DataList;
184
+ if (options.outputFilter) {
185
+ const outputFilter = Util.createFilterHandler(options.outputFilter, (entry) => entry.sourcePath);
186
+ filteredV8DataList = v8DataList.filter(outputFilter);
187
+ // Keep V8 and converted Istanbul reports in sync.
188
+ const sourcePaths = new Set(filteredV8DataList.map((entry) => entry.sourcePath));
189
+ Object.keys(coverageData).forEach((sourcePath) => {
190
+ if (!sourcePaths.has(sourcePath)) {
191
+ delete coverageData[sourcePath];
192
+ delete fileSources[sourcePath];
193
+ }
194
+ });
195
+ }
196
+
197
+ return generateV8ListReports(filteredV8DataList, coverageData, fileSources, options);
185
198
  }
186
199
 
187
200
  // istanbul data
188
201
  const t3 = Date.now();
202
+ const { mergeIstanbulCoverage, saveIstanbulReports } = await import('./istanbul/istanbul.js');
189
203
  const istanbulData = await mergeIstanbulCoverage(dataList, options);
190
204
  Util.logTime(`${EC.magenta('├')} [generate] prepared istanbul coverage data`, t3);
191
205
  const fileSources = options.fileSources || {};
@@ -277,6 +291,8 @@ const addDirData = async (mcr, dataList, sourceCache, dir) => {
277
291
  };
278
292
 
279
293
  const addZipData = async (mcr, dataList, sourceCache, dir) => {
294
+ const { default: StreamZipModule } = await import('node-stream-zip');
295
+ const StreamZip = StreamZipModule.async;
280
296
  const zip = new StreamZip({
281
297
  file: dir
282
298
  });
@@ -327,7 +343,9 @@ const getInputData = async (mcr) => {
327
343
  return;
328
344
  }
329
345
  // No coverage input: use V8 so `all` can add untested files.
330
- dataList.push({ type: 'v8', data: [] });
346
+ dataList.push({
347
+ type: 'v8', data: []
348
+ });
331
349
  }
332
350
 
333
351
  return {
@@ -491,7 +509,7 @@ const readFromDir = async (mcr, dir) => {
491
509
 
492
510
  };
493
511
 
494
- module.exports = {
512
+ export {
495
513
  getInputData,
496
514
  readFromDir,
497
515
  generateCoverageReports
package/lib/index.d.ts CHANGED
@@ -322,6 +322,14 @@ declare namespace MCR {
322
322
  [pattern: string]: boolean;
323
323
  } | ((sourcePath: string) => boolean);
324
324
 
325
+ /** (V8 only) Filter final files after sourcemap conversion and adding untested files.
326
+ * Applies to V8 reports and converted Istanbul reports. Defaults to null (disabled).
327
+ * Strings and object keys match sourcePath using the same rules as entryFilter and sourceFilter.
328
+ */
329
+ outputFilter?: string | {
330
+ [pattern: string]: boolean;
331
+ } | ((entry: CoverageFile) => boolean) | null;
332
+
325
333
  /**
326
334
  * The combined filter for entryFilter and sourceFilter
327
335
  */
@@ -405,7 +413,7 @@ declare namespace MCR {
405
413
  cleanCache?: boolean;
406
414
 
407
415
  /**
408
- * {number} gc threshold
416
+ * {number} JavaScript heapUsed threshold in MB
409
417
  * for example: sets gc to 1024 means that force gc when the memory > 1024M at certain critical stages
410
418
  * https://nodejs.org/docs/latest/api/v8.html#v8setflagsfromstringflags
411
419
  */
@@ -432,6 +440,15 @@ declare namespace MCR {
432
440
 
433
441
  export interface McrCliOptions extends CoverageReportOptions {
434
442
 
443
+ /** Only used by `mcr test`. Test file paths or glob patterns accepted by node --test.
444
+ * A string is one positional argument; an array supplies multiple arguments unchanged.
445
+ * Node handles parsing and discovery relative to cwd; null is not passed to Node.
446
+ * Positional CLI targets override this option.
447
+ * Defaults to null (skip tests unless CLI targets are supplied).
448
+ * Requires Node.js >= 22.15.0. Ignored by other commands and the API.
449
+ */
450
+ test?: string | string[] | null;
451
+
435
452
  /** (CLI only) {function} onStart hook */
436
453
  onStart?: (coverageReport: CoverageReport) => void | Promise<void>;
437
454
 
@@ -479,6 +496,8 @@ declare namespace MCR {
479
496
  /** load config file.
480
497
  *
481
498
  * @param configFile custom config file path
499
+ * Throws if a custom config is missing or a discovered config fails to load.
500
+ * If no custom config is specified and no default config is found, returns normally.
482
501
  *
483
502
  * Supports loading default config file if no custom config specified:
484
503
  'mcr.config.js',
@@ -532,6 +551,9 @@ declare namespace MCR {
532
551
  //=====================================================================================================
533
552
 
534
553
  export class CoverageClient {
554
+ /** Best-effort command: logs failures at debug level and resolves to null instead of rejecting. */
555
+ safeSend: (method: string, params?: any) => Promise<any>;
556
+
535
557
  /** start js coverage */
536
558
  startJSCoverage: () => Promise<void>;
537
559
  /** stop and return js coverage */
@@ -567,7 +589,8 @@ declare namespace MCR {
567
589
 
568
590
  /** custom websocket CDPSession */
569
591
  export class WSSession implements CDPSession {
570
- constructor(ws: any);
592
+ /** Request timeout defaults to 30000ms; 0 disables the deadline. */
593
+ constructor(ws: any, options?: { timeout?: number });
571
594
  send: (method: string, params?: any) => Promise<any>;
572
595
  on: (type: string, handler: (e: any) => void) => void;
573
596
  detach: () => Promise<void>;
@@ -588,8 +611,10 @@ declare namespace MCR {
588
611
  target?: (targets: any) => any;
589
612
  /** websocket options */
590
613
  ws?: any;
591
- /** timeout, defaults to 10 * 1000 */
614
+ /** HTTP discovery / WebSocket connection timeout, defaults to 10000ms; 0 disables it. */
592
615
  timeout?: number;
616
+ /** Per-command timeout for built-in WebSocket sessions, defaults to 30000ms; 0 disables it. */
617
+ requestTimeout?: number;
593
618
  }
594
619
 
595
620
  export function CDPClient(cdpOptions: CDPOptions): Promise<CoverageClient | undefined>;
@@ -603,4 +628,27 @@ declare namespace MCR {
603
628
  /** create coverage report */
604
629
  declare function MCR(options?: MCR.CoverageReportOptions): MCR.CoverageReport;
605
630
 
606
- export = MCR;
631
+ export { MCR as default, MCR };
632
+ export import V8CoverageEntry = MCR.V8CoverageEntry;
633
+ export import Watermarks = MCR.Watermarks;
634
+ export import ReportDescription = MCR.ReportDescription;
635
+ export import AddedResults = MCR.AddedResults;
636
+ export import MetricsSummary = MCR.MetricsSummary;
637
+ export import CoverageSummary = MCR.CoverageSummary;
638
+ export import CoverageRange = MCR.CoverageRange;
639
+ export import IgnoredRange = MCR.IgnoredRange;
640
+ export import CoverageFile = MCR.CoverageFile;
641
+ export import CoverageResults = MCR.CoverageResults;
642
+ export import LoggingType = MCR.LoggingType;
643
+ export import CoverageReportOptions = MCR.CoverageReportOptions;
644
+ export import McrCliOptions = MCR.McrCliOptions;
645
+ export import CoverageSnapshot = MCR.CoverageSnapshot;
646
+ export import CoverageClient = MCR.CoverageClient;
647
+ export import CDPSession = MCR.CDPSession;
648
+ export import CDPOptions = MCR.CDPOptions;
649
+ export import CoverageReport = MCR.CoverageReport;
650
+ export import getSnapshot = MCR.getSnapshot;
651
+ export import diffSnapshot = MCR.diffSnapshot;
652
+ export import WSSession = MCR.WSSession;
653
+ export import CDPClient = MCR.CDPClient;
654
+ export import Util = MCR.Util;
package/lib/index.js CHANGED
@@ -1,46 +1,41 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { pathToFileURL } = require('url');
4
- const EC = require('eight-colors');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import EC from 'eight-colors';
5
5
 
6
- const defaultOptions = require('./default/options.js');
7
- const Util = require('./utils/util.js');
6
+ import { defaultOptions } from './default/options.js';
7
+ import { Util } from './utils/util.js';
8
8
 
9
- const { initV8ListAndSourcemap } = require('./v8/v8.js');
10
- const {
9
+ import { initV8ListAndSourcemap } from './v8/v8.js';
10
+ import {
11
11
  getInputData, readFromDir, generateCoverageReports
12
- } = require('./generate.js');
13
- const { getSnapshot, diffSnapshot } = require('./utils/snapshot.js');
12
+ } from './generate.js';
13
+ import { getSnapshot, diffSnapshot } from './utils/snapshot.js';
14
14
 
15
- const WSSession = require('./client/ws-session.js');
16
- const CDPClient = require('./client/cdp-client.js');
15
+ import { WSSession } from './client/ws-session.js';
16
+ import { CDPClient } from './client/cdp-client.js';
17
+ import { CoverageClient } from './client/coverage-client.js';
17
18
 
18
19
  const resolveConfigOptions = async (configPath) => {
19
- // json format
20
- const ext = path.extname(configPath);
21
- if (ext === '.json' || configPath.slice(-2) === 'rc') {
22
- return JSON.parse(Util.readFileSync(configPath));
23
- }
24
-
25
- let configOptions;
26
- let err;
27
20
  try {
28
- configOptions = await import(pathToFileURL(configPath));
29
- } catch (ee) {
30
- err = ee;
31
- }
32
-
33
- if (err) {
34
- Util.logError(`ERROR: failed to load config "${configPath}": ${err && err.message} `);
35
- return;
36
- }
21
+ // json format
22
+ const ext = path.extname(configPath);
23
+ if (ext === '.json' || configPath.slice(-2) === 'rc') {
24
+ return JSON.parse(Util.readFileSync(configPath));
25
+ }
37
26
 
38
- // could be multiple level default
39
- while (configOptions && configOptions.default) {
40
- configOptions = configOptions.default;
27
+ let configOptions = await import(pathToFileURL(configPath));
28
+ // could be multiple level default
29
+ while (configOptions && configOptions.default) {
30
+ configOptions = configOptions.default;
31
+ }
32
+ return configOptions;
33
+ } catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ throw new Error(`Failed to load config file "${configPath}": ${message}`, {
36
+ cause: error
37
+ });
41
38
  }
42
-
43
- return configOptions;
44
39
  };
45
40
 
46
41
  class CoverageReport {
@@ -237,7 +232,7 @@ class CoverageReport {
237
232
  const configPath = Util.findUpConfig(customConfigFile);
238
233
  if (!configPath) {
239
234
  if (customConfigFile) {
240
- Util.logError(`The config file does not exist: ${customConfigFile}`);
235
+ throw new Error(`The config file does not exist: ${customConfigFile}`);
241
236
  }
242
237
  // not found config
243
238
  return;
@@ -245,11 +240,7 @@ class CoverageReport {
245
240
 
246
241
  const configOptions = await resolveConfigOptions(configPath);
247
242
  if (!configOptions) {
248
- // failed to load config options
249
- if (customConfigFile) {
250
- Util.logError(`Failed to load config file: ${customConfigFile}`);
251
- }
252
- return;
243
+ throw new Error(`Failed to load config file: ${configPath}`);
253
244
  }
254
245
 
255
246
  Util.logInfo(`Loaded: ${EC.cyan(Util.relativePath(configPath))}`);
@@ -271,10 +262,13 @@ const MCR = function(options) {
271
262
  return new CoverageReport(options);
272
263
  };
273
264
  MCR.CoverageReport = CoverageReport;
265
+ MCR.CoverageClient = CoverageClient;
274
266
  MCR.getSnapshot = getSnapshot;
275
267
  MCR.diffSnapshot = diffSnapshot;
276
268
  MCR.WSSession = WSSession;
277
269
  MCR.CDPClient = CDPClient;
278
270
  MCR.Util = Util;
279
271
 
280
- module.exports = MCR;
272
+ export {
273
+ MCR as default, MCR, CoverageReport, CoverageClient, getSnapshot, diffSnapshot, WSSession, CDPClient, Util
274
+ };
@@ -1,4 +1,4 @@
1
- const istanbulLibReport = require('istanbul-lib-report');
1
+ import istanbulLibReport from 'istanbul-lib-report';
2
2
 
3
3
  const ReportBase = istanbulLibReport.ReportBase;
4
4
  class IstanbulSummary extends ReportBase {
@@ -70,4 +70,4 @@ class IstanbulSummary extends ReportBase {
70
70
  }
71
71
 
72
72
 
73
- module.exports = IstanbulSummary;
73
+ export { IstanbulSummary };
@@ -1,15 +1,15 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const istanbulReports = require('istanbul-reports');
4
- const istanbulLibCoverage = require('istanbul-lib-coverage');
5
- const istanbulLibReport = require('istanbul-lib-report');
6
- const EC = require('eight-colors');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import istanbulLibCoverage from 'istanbul-lib-coverage';
5
+ import istanbulLibReport from 'istanbul-lib-report';
6
+ import EC from 'eight-colors';
7
7
 
8
- const Util = require('../utils/util.js');
9
- const IstanbulSummary = require('./istanbul-summary.js');
8
+ import { Util } from '../utils/util.js';
9
+ import { IstanbulSummary } from './istanbul-summary.js';
10
10
 
11
- const { initIstanbulSourcePath } = require('../utils/source-path.js');
12
- const { getUntestedList } = require('../converter/untested.js');
11
+ import { initIstanbulSourcePath } from '../utils/source-path.js';
12
+ import { getUntestedList } from '../converter/untested.js';
13
13
 
14
14
  const findHtmlPath = (outputDir) => {
15
15
  const defaultHtml = path.resolve(outputDir, 'index.html');
@@ -35,7 +35,29 @@ const findHtmlPath = (outputDir) => {
35
35
 
36
36
  };
37
37
 
38
- const saveIstanbulReports = (coverageData, fileSources, options) => {
38
+ const createIstanbulReport = async (name, options) => {
39
+ let reporter;
40
+ const isFile = path.isAbsolute(name) || name.startsWith('.');
41
+ // Built-in reports remain CommonJS dependencies; custom reports may be ESM.
42
+ if (!isFile) {
43
+ try {
44
+ reporter = await import(`istanbul-reports/lib/${name}/index.js`);
45
+ } catch (error) {
46
+ if (error.code !== 'ERR_MODULE_NOT_FOUND') {
47
+ throw error;
48
+ }
49
+ }
50
+ }
51
+ if (!reporter) {
52
+ // Native import() also handles CJS reporters without a separate loader.
53
+ const specifier = isFile ? pathToFileURL(path.resolve(name)).href : name;
54
+ reporter = await import(specifier);
55
+ }
56
+ const Reporter = reporter.default || reporter;
57
+ return new Reporter(options);
58
+ };
59
+
60
+ const saveIstanbulReports = async (coverageData, fileSources, options) => {
39
61
 
40
62
  coverageData = initIstanbulSourcePath(coverageData, fileSources, options);
41
63
 
@@ -96,7 +118,7 @@ const saveIstanbulReports = (coverageData, fileSources, options) => {
96
118
  if (istanbulGroup) {
97
119
  for (const [reportName, reportOptions] of istanbulGroup) {
98
120
  const t1 = Date.now();
99
- const report = istanbulReports.create(reportName, reportOptions);
121
+ const report = await createIstanbulReport(reportName, reportOptions);
100
122
  report.execute(context);
101
123
  Util.logTime(`${EC.magenta('├')} [generate] saved report: ${reportName}`, t1);
102
124
  }
@@ -163,7 +185,7 @@ const mergeIstanbulCoverage = async (dataList, options) => {
163
185
  return istanbulData;
164
186
  };
165
187
 
166
- module.exports = {
188
+ export {
167
189
  saveIstanbulReports,
168
190
  mergeIstanbulDataList,
169
191
  mergeIstanbulCoverage