monocart-coverage-reports 2.12.10 → 2.12.11

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/README.md CHANGED
@@ -26,7 +26,7 @@
26
26
  * [Filtering Results](#filtering-results)
27
27
  * [Resolve `sourcePath` for the Source Files](#resolve-sourcepath-for-the-source-files)
28
28
  * [Adding Empty Coverage for Untested Files](#adding-empty-coverage-for-untested-files)
29
- * [onEnd Hook](#onend-hook)
29
+ * [Hooks](#hooks)
30
30
  * [Ignoring Uncovered Codes](#ignoring-uncovered-codes)
31
31
  * [Multiprocessing Support](#multiprocessing-support)
32
32
  * [Command Line](#command-line)
@@ -102,9 +102,40 @@ For more information, see [Command Line](#command-line)
102
102
  - Options declaration see `CoverageReportOptions` [lib/index.d.ts](./lib/index.d.ts)
103
103
  - [Config file](#config-file)
104
104
 
105
+ | Option | Type | Default | Description |
106
+ | :-- | :-- | :-- | :-- |
107
+ | `logging` | `"off" \| "error" \| "info" \| "debug"` | `"info"` | Logging level. Use `"debug"` to keep raw cache and dump sourcemaps for troubleshooting. See [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap). |
108
+ | `name` | `string` | `"Coverage Report"` | Report title shown in the UI and summary reports. |
109
+ | `reports` | `string \| (string \| ReportDescription)[]` | `"v8"` (V8) / `"html"` (Istanbul) | Reports to generate. See [Available Reports](#available-reports). |
110
+ | `outputDir` | `string` | `"./coverage-reports"` | Output directory for all reports and the `.cache` folder. |
111
+ | `inputDir` | `string \| string[]` | `null` | Input directories of raw coverage data for [merging](#merge-coverage-reports). |
112
+ | `baseDir` | `string` | `process.cwd()` | Base dir used to normalize relative source paths. Set when the report is generated from a different working directory than the sources. |
113
+ | `dataDir` | `string` | `null` | Coverage data directory loaded automatically in `generate()` — alternative to `addFromDir()`. |
114
+ | `entryFilter` | `string \| object \| function` | `null` | (V8 only) Filter V8 entries by url. See [Filtering Results](#filtering-results). |
115
+ | `sourceFilter` | `string \| object \| function` | `null` | (V8 only) Filter sources unpacked from sourcemaps. |
116
+ | `filter` | `string \| object \| function` | `null` | Combined filter replacing both `entryFilter` and `sourceFilter`. |
117
+ | `sourcePath` | `object \| function` | `null` | Rewrite source paths; see [Resolve `sourcePath`](#resolve-sourcepath-for-the-source-files). |
118
+ | `all` | `string \| string[] \| object` | `null` | Include untested files as empty coverage. See [Adding Empty Coverage](#adding-empty-coverage-for-untested-files). |
119
+ | `outputFile` | `string` | `"index.html"` | (V8 only) Output `[sub dir/]filename` for the V8 report. |
120
+ | `inline` | `boolean` | `false` | (V8 only) Inline all assets into a single HTML file. |
121
+ | `assetsPath` | `string` | `"./assets"` | (V8 only) Assets directory when `inline` is false. |
122
+ | `lcov` | `boolean` | `false` | Also generate `lcov.info` (equivalent to adding the `lcovonly` report). |
123
+ | `v8Ignore` | `boolean` | `true` | (V8 only) Enable/disable comment-based ignoring (`v8 ignore …`). See [Ignoring Uncovered Codes](#ignoring-uncovered-codes). |
124
+ | `reportPath` | `string \| () => string` | `null` | Override the report entry path (defaults to `outputDir/index.html`). Useful when multiple reports share an `outputDir`. |
125
+ | `watermarks` | `[number, number] \| object` | `[50, 80]` | Low/high thresholds (percent). Accepts per-metric object like `{ bytes:[50,80], lines:[50,80] }`. |
126
+ | `clean` | `boolean` | `true` | Clean previous reports in `outputDir` before generating. |
127
+ | `cleanCache` | `boolean` | `false` | Clean the cache dir on start. |
128
+ | `gc` | `number` | `null` | Memory threshold in MB; force GC at critical stages when RSS exceeds it. Useful for very large data sets, see [JavaScript heap out of memory](#javascript-heap-out-of-memory). |
129
+ | `sourceMap` | `boolean` | `false` | Save source/sourcemap files to cache for debugging (requires `logging: "debug"`). |
130
+ | `sourceMapResolver` | `(url, defaultResolver) => Promise<string \| object>` | `null` | Custom sourcemap loader (e.g. from a build cache). Call `defaultResolver(url)` to fall back. |
131
+ | `onEntry` | `(entry) => void \| Promise<void>` | `null` | (V8 only) Per-entry hook; see [Hooks](#hooks). |
132
+ | `onEnd` | `(coverageResults) => void \| Promise<void>` | `null` | Hook invoked after report generation; see [Hooks](#hooks). |
133
+ | `onStart` | `(coverageReport) => void \| Promise<void>` | `null` | (CLI only) Before the child process starts; see [Hooks](#hooks). |
134
+ | `onReady` | `(coverageReport, nodeV8CoverageDir, subprocess) => void \| Promise<void>` | `null` | (CLI only) After the child exits, before MCR reads coverage data; see [Hooks](#hooks). |
135
+
105
136
  ## Available Reports
106
137
 
107
- > V8 build-in reports (V8 data only):
138
+ > V8 built-in reports (V8 data only):
108
139
 
109
140
  - `v8`
110
141
  - Features:
@@ -124,7 +155,7 @@ For more information, see [Command Line](#command-line)
124
155
 
125
156
  ![](./assets/mcv.gif)
126
157
 
127
- > Istanbul build-in reports (both V8 and Istanbul data):
158
+ > Istanbul built-in reports (both V8 and Istanbul data):
128
159
 
129
160
  - `clover`
130
161
  - `cobertura`
@@ -144,7 +175,7 @@ For more information, see [Command Line](#command-line)
144
175
  - `text-lcov`
145
176
  - `text-summary`
146
177
 
147
- > Other build-in reports (both V8 and Istanbul data):
178
+ > Other built-in reports (both V8 and Istanbul data):
148
179
 
149
180
  - `codecov` Save coverage data to a json file with [Codecov](https://docs.codecov.com/docs/codecov-custom-coverage-format) format (defaults to `codecov.json`), see [example](https://app.codecov.io/github/cenfun/monocart-coverage-reports).
150
181
 
@@ -198,7 +229,7 @@ const MCR = require('monocart-coverage-reports');
198
229
  const coverageOptions = {
199
230
  outputDir: './coverage-reports',
200
231
  reports: [
201
- // build-in reports
232
+ // built-in reports
202
233
  ['console-summary'],
203
234
  ['v8'],
204
235
  ['html', {
@@ -464,7 +495,7 @@ export interface CoverageRange {
464
495
  * @functionName can be an empty string.
465
496
  * @ranges is always non-empty. The first range is called the "root range".
466
497
  * @isBlockCoverage indicates if the function has block coverage information.
467
- If this is false, it usually means that the functions was never called.
498
+ If this is false, it usually means that the function was never called.
468
499
  It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0.
469
500
  */
470
501
  export interface FunctionCoverage {
@@ -572,7 +603,7 @@ const coverageOptions = {
572
603
  filter: {
573
604
  '**/node_modules/**': false,
574
605
  '**/vendor.js': false,
575
- '**/src/**': true
606
+ '**/src/**': true,
576
607
  '**/**': true
577
608
  }
578
609
  };
@@ -672,8 +703,10 @@ const coverageOptions = {
672
703
  };
673
704
  ```
674
705
 
675
- ## onEnd Hook
676
- For example, checking thresholds:
706
+ ## Hooks
707
+
708
+ ### `onEnd` — after the report is generated
709
+ Typical use case: enforce coverage thresholds.
677
710
  ```js
678
711
  const EC = require('eight-colors');
679
712
  const coverageOptions = {
@@ -703,6 +736,29 @@ const coverageOptions = {
703
736
  }
704
737
  ```
705
738
 
739
+ ### `onEntry` — before each V8 entry is processed (V8 only)
740
+ Use this to mutate the entry (for example, transform non-standard sources into valid ECMAScript before the AST parser runs). See [Unparsable source](#unparsable-source).
741
+ ```js
742
+ const coverageOptions = {
743
+ onEntry: async (entry) => {
744
+ // entry.source, entry.sourceMap, entry.fake, ...
745
+ }
746
+ };
747
+ ```
748
+
749
+ ### `onStart` / `onReady` — CLI-only
750
+ Only available when using `mcr <command>`:
751
+ - `onStart(coverageReport)` — runs before the child process is spawned.
752
+ - `onReady(coverageReport, nodeV8CoverageDir, subprocess)` — runs after the child exits, before MCR reads coverage from `nodeV8CoverageDir`. Useful when the child hasn't finished flushing coverage data and needs to be waited on.
753
+ ```js
754
+ // mcr.config.js
755
+ module.exports = {
756
+ onReady: async (coverageReport, nodeV8CoverageDir, subprocess) => {
757
+ // wait for something, or pre-process the raw files
758
+ }
759
+ };
760
+ ```
761
+
706
762
  ## Ignoring Uncovered Codes
707
763
  To ignore codes, use the special comment which starts with `v8 ignore `:
708
764
  - Ignoring all until stop
@@ -715,9 +771,9 @@ function uncovered() {
715
771
  - Ignoring the next line or next N lines
716
772
  ```js
717
773
  /* v8 ignore next */
718
- const os = platform === 'wind32' ? 'Windows' : 'Other';
774
+ const os = platform === 'win32' ? 'Windows' : 'Other';
719
775
 
720
- const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other';
776
+ const os = platform === 'win32' ? 'Windows' /* v8 ignore next */ : 'Other';
721
777
 
722
778
  // v8 ignore next 3
723
779
  if (platform === 'linux') {
@@ -736,6 +792,7 @@ function uncovered() {
736
792
  }
737
793
  /* node:coverage enable */
738
794
  ```
795
+ - To disable comment-based ignoring entirely, set `v8Ignore: false`.
739
796
 
740
797
  ## Multiprocessing Support
741
798
  > The data will be added to `[outputDir]/.cache`, After the generation of the report, this data will be removed unless debugging has been enabled or a raw report has been used, see [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
@@ -797,6 +854,16 @@ see all options with running `mcr` or `mcr --help`
797
854
  mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js
798
855
  ```
799
856
 
857
+ - `--import <module>` / `--require <module>`: forward a preload module to the child process via `NODE_OPTIONS`. Use this for TypeScript/JSX runtimes (`tsx`, `ts-node`, etc.) and also when loading a `mcr.config.ts`. Requires Node.js `>= 18.19`.
858
+ ```sh
859
+ mcr --import tsx node ./test.ts
860
+ ```
861
+
862
+ - `--env [path]`: load environment variables from a dotenv file before the child starts (defaults to `.env`). Requires `process.loadEnvFile`, added in Node.js `20.6`.
863
+ ```sh
864
+ mcr --env .env.test node ./test.js
865
+ ```
866
+
800
867
  - Examples
801
868
  - [Mocha](#mocha)
802
869
  - [TypeScript](#typescript)
@@ -811,7 +878,12 @@ Loading config file by priority:
811
878
  - `mcr.config.cjs`
812
879
  - `mcr.config.mjs`
813
880
  - `mcr.config.json` - json format
814
- - `mcr.config.ts` (requires preloading the ts execution module)
881
+ - `mcr.config.ts` (requires preloading the TypeScript execution module, for example with `tsx`):
882
+ ```sh
883
+ mcr --import tsx -c mcr.config.ts node ./test.js
884
+ ```
885
+
886
+ > If no custom path is given, MCR walks up from the current working directory to find the default config file (via [`find-up`](https://github.com/sindresorhus/find-up)). Files outside the search path will be ignored.
815
887
 
816
888
  ## Merge Coverage Reports
817
889
  The following usage scenarios may require merging coverage reports:
@@ -890,7 +962,7 @@ const coverageOptions = {
890
962
  ],
891
963
 
892
964
  onEnd: () => {
893
- // remove the raw files if it useless
965
+ // remove the raw files if no longer needed
894
966
  // inputDir.forEach((p) => {
895
967
  // fs.rmSync(p, {
896
968
  // recursive: true,
@@ -926,8 +998,8 @@ In the generated code, there is a position `p`, and we need to find out its corr
926
998
  - Further understanding of sourcemap, try [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
927
999
 
928
1000
  How `MCR` Works:
929
- - 1, Trying to fix the original position with string comparison and [`diff-sequences`](https://github.com/jestjs/jest/tree/main/packages/diff-sequences). However, for non-JS code, such as Vue template, JSX, etc., it might be hard to find a perfect solution.
930
- - 2, Finding all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn). (There is a small issue is the V8 cannot provide effective branch coverage information for `AssignmentPattern`)
1001
+ 1. Tries to fix the original position with string comparison and [`diff-sequences`](https://github.com/jestjs/jest/tree/main/packages/diff-sequences). However, for non-JS code such as Vue templates or JSX, a perfect solution may not always be possible.
1002
+ 2. Finds all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn). (One small caveat: V8 cannot provide effective branch coverage information for `AssignmentPattern`.)
931
1003
 
932
1004
 
933
1005
  ### Unparsable source
@@ -971,7 +1043,7 @@ const coverageOptions = {
971
1043
  ]
972
1044
  };
973
1045
  ```
974
- When `logging` is `debug`, the raw report data will be preserved in `[outputDir]/.cache` or `[outputDir]/raw` if `raw` report is used. And the dist file will be preserved in the V8 list, and by opening the browser's devtool, it makes data verification visualization effortless.
1046
+ When `logging` is `debug`, the raw report data is preserved in `[outputDir]/.cache` (or `[outputDir]/raw` if the `raw` report is used). The dist file is also kept in the V8 list, so you can open the browser's devtools and visually verify the coverage data.
975
1047
  ![](./assets/debug-coverage.png)
976
1048
 
977
1049
  - Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/)
package/README.zh-Hans.md CHANGED
@@ -26,7 +26,7 @@
26
26
  * [过滤V8覆盖率数据](#filtering-results)
27
27
  * [使用 `sourcePath` 修改源文件路径](#resolve-sourcepath-for-the-source-files)
28
28
  * [为未测试的文件添加空的覆盖率报告](#adding-empty-coverage-for-untested-files)
29
- * [onEnd回调函数](#onend-hook)
29
+ * [回调钩子 Hooks](#hooks)
30
30
  * [如何忽略未覆盖的代码](#ignoring-uncovered-codes)
31
31
  * [多进程支持](#multiprocessing-support)
32
32
  * [如何使用CLI命令行](#command-line)
@@ -102,6 +102,37 @@ mcr node my-app.js -r v8,console-details
102
102
  - 选项的类型描述,见 `CoverageReportOptions` [lib/index.d.ts](./lib/index.d.ts)
103
103
  - [配置文件](#config-file)
104
104
 
105
+ | 选项 | 类型 | 默认值 | 说明 |
106
+ | :-- | :-- | :-- | :-- |
107
+ | `logging` | `"off" \| "error" \| "info" \| "debug"` | `"info"` | 日志级别。设为 `"debug"` 会保留原始缓存并输出 sourcemap,便于排查问题。参见 [调试覆盖率和sourcemap](#debug-for-coverage-and-sourcemap)。 |
108
+ | `name` | `string` | `"Coverage Report"` | 报告标题,显示在 UI 以及 summary 报告中。 |
109
+ | `reports` | `string \| (string \| ReportDescription)[]` | V8 默认 `"v8"` / Istanbul 默认 `"html"` | 生成哪些报告,参见 [所有支持的报告类型](#available-reports)。 |
110
+ | `outputDir` | `string` | `"./coverage-reports"` | 所有报告以及 `.cache` 的输出目录。 |
111
+ | `inputDir` | `string \| string[]` | `null` | 导入的原始覆盖率数据目录(用于 [合并](#merge-coverage-reports))。 |
112
+ | `baseDir` | `string` | `process.cwd()` | 规范化相对源路径的基准目录。当生成报告的工作目录和源码目录不一致时需要设置。 |
113
+ | `dataDir` | `string` | `null` | `generate()` 阶段自动加载的覆盖率数据目录,作为 `addFromDir()` 的替代。 |
114
+ | `entryFilter` | `string \| object \| function` | `null` | (仅 V8)按 URL 过滤入口文件,参见 [过滤V8覆盖率数据](#filtering-results)。 |
115
+ | `sourceFilter` | `string \| object \| function` | `null` | (仅 V8)过滤从 sourcemap 解包出的源文件。 |
116
+ | `filter` | `string \| object \| function` | `null` | 合并 `entryFilter` 和 `sourceFilter` 的统一过滤器。 |
117
+ | `sourcePath` | `object \| function` | `null` | 修改源文件路径,参见 [使用 `sourcePath`](#resolve-sourcepath-for-the-source-files)。 |
118
+ | `all` | `string \| string[] \| object` | `null` | 为未测试文件添加空覆盖率,参见 [为未测试的文件添加空的覆盖率报告](#adding-empty-coverage-for-untested-files)。 |
119
+ | `outputFile` | `string` | `"index.html"` | (仅 V8)V8 报告的 `[子目录/]文件名`。 |
120
+ | `inline` | `boolean` | `false` | (仅 V8)将所有资源内联到单一 HTML 文件。 |
121
+ | `assetsPath` | `string` | `"./assets"` | (仅 V8)非内联模式下的资源目录。 |
122
+ | `lcov` | `boolean` | `false` | 额外生成 `lcov.info`,等同于添加 `lcovonly` 报告。 |
123
+ | `v8Ignore` | `boolean` | `true` | (仅 V8)启用/禁用基于注释的忽略(`v8 ignore …`),参见 [忽略未覆盖代码](#ignoring-uncovered-codes)。 |
124
+ | `reportPath` | `string \| () => string` | `null` | 覆盖默认的报告入口路径(默认 `outputDir/index.html`)。多个报告共用同一 `outputDir` 时很有用。 |
125
+ | `watermarks` | `[number, number] \| object` | `[50, 80]` | 覆盖率高/低阈值百分比。也支持按指标配置:`{ bytes:[50,80], lines:[50,80] }`。 |
126
+ | `clean` | `boolean` | `true` | 生成报告前清理 `outputDir` 中的旧报告。 |
127
+ | `cleanCache` | `boolean` | `false` | 启动时清理缓存目录。 |
128
+ | `gc` | `number` | `null` | 内存阈值(MB),在关键阶段若 RSS 超过阈值则强制触发 GC,适用于超大数据集,参见 [JavaScript heap out of memory](#javascript-heap-out-of-memory)。 |
129
+ | `sourceMap` | `boolean` | `false` | 将源文件和 sourcemap 也保存到 cache 便于调试(需要 `logging: "debug"`)。 |
130
+ | `sourceMapResolver` | `(url, defaultResolver) => Promise<string \| object>` | `null` | 自定义 sourcemap 加载逻辑(例如从构建缓存中读取),可调用 `defaultResolver(url)` 回退到默认解析。 |
131
+ | `onEntry` | `(entry) => void \| Promise<void>` | `null` | (仅 V8)每个入口文件处理前触发,参见 [Hooks](#hooks)。 |
132
+ | `onEnd` | `(coverageResults) => void \| Promise<void>` | `null` | 报告生成完成后触发,参见 [Hooks](#hooks)。 |
133
+ | `onStart` | `(coverageReport) => void \| Promise<void>` | `null` | (仅 CLI)子进程启动前触发,参见 [Hooks](#hooks)。 |
134
+ | `onReady` | `(coverageReport, nodeV8CoverageDir, subprocess) => void \| Promise<void>` | `null` | (仅 CLI)子进程退出后、MCR 读取覆盖率数据前触发,参见 [Hooks](#hooks)。 |
135
+
105
136
  ## Available Reports
106
137
 
107
138
  > 内置V8报告(仅V8格式数据支持):
@@ -199,7 +230,7 @@ const MCR = require('monocart-coverage-reports');
199
230
  const coverageOptions = {
200
231
  outputDir: './coverage-reports',
201
232
  reports: [
202
- // build-in reports
233
+ // built-in reports
203
234
  ['console-summary'],
204
235
  ['v8'],
205
236
  ['html', {
@@ -468,7 +499,7 @@ export interface CoverageRange {
468
499
  * @functionName can be an empty string.
469
500
  * @ranges is always non-empty. The first range is called the "root range".
470
501
  * @isBlockCoverage indicates if the function has block coverage information.
471
- If this is false, it usually means that the functions was never called.
502
+ If this is false, it usually means that the function was never called.
472
503
  It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0.
473
504
  */
474
505
  export interface FunctionCoverage {
@@ -502,7 +533,7 @@ export type V8CoverageData = ScriptCoverage[];
502
533
  | Bun | ❌ | |
503
534
 
504
535
  ## Filtering Results
505
- ## Using `entryFilter` and `sourceFilter` to filter the results for V8 report
536
+ ### Using `entryFilter` and `sourceFilter` to filter the results for V8 report
506
537
  当收集到V8的覆盖数据时,它实际上包含了所有的入口文件的覆盖率数据, 比如有以下3个文件:
507
538
 
508
539
  - *dist/main.js*
@@ -576,7 +607,7 @@ const coverageOptions = {
576
607
  filter: {
577
608
  '**/node_modules/**': false,
578
609
  '**/vendor.js': false,
579
- '**/src/**': true
610
+ '**/src/**': true,
580
611
  '**/**': true
581
612
  }
582
613
  };
@@ -675,8 +706,10 @@ const coverageOptions = {
675
706
  };
676
707
  ```
677
708
 
678
- ## onEnd Hook
679
- 结束回调可以用来自定义业务需求,比如检测覆盖率是否达标,对比每个指标的thresholds,如果低于要求的值则可以抛出一个错误退出
709
+ ## Hooks
710
+
711
+ ### `onEnd` — 报告生成后触发
712
+ 典型用法:检测覆盖率是否达标,低于 threshold 时抛错退出。
680
713
  ```js
681
714
  const EC = require('eight-colors');
682
715
  const coverageOptions = {
@@ -706,6 +739,29 @@ const coverageOptions = {
706
739
  }
707
740
  ```
708
741
 
742
+ ### `onEntry` — 每个V8入口在处理前触发(仅V8)
743
+ 可以在进入AST解析前改写 entry(例如对非标准语法的源码做预编译),参见 [Unparsable source](#unparsable-source)
744
+ ```js
745
+ const coverageOptions = {
746
+ onEntry: async (entry) => {
747
+ // entry.source, entry.sourceMap, entry.fake, ...
748
+ }
749
+ };
750
+ ```
751
+
752
+ ### `onStart` / `onReady` — 仅CLI可用
753
+ 只在使用 `mcr <command>` 时有效:
754
+ - `onStart(coverageReport)` — 子进程启动前触发
755
+ - `onReady(coverageReport, nodeV8CoverageDir, subprocess)` — 子进程退出后、MCR 读取 `nodeV8CoverageDir` 之前触发。用于子进程尚未写完覆盖数据需要等待的场景
756
+ ```js
757
+ // mcr.config.js
758
+ module.exports = {
759
+ onReady: async (coverageReport, nodeV8CoverageDir, subprocess) => {
760
+ // 等待某个信号,或先对 raw 文件做一些预处理
761
+ }
762
+ };
763
+ ```
764
+
709
765
  ## Ignoring Uncovered Codes
710
766
  使用特定的注释,以`v8 ignore `开头可以忽略未覆盖的代码:
711
767
  - 忽略开始到结束
@@ -718,9 +774,9 @@ function uncovered() {
718
774
  - 忽略接下来一行或者多行
719
775
  ```js
720
776
  /* v8 ignore next */
721
- const os = platform === 'wind32' ? 'Windows' : 'Other';
777
+ const os = platform === 'win32' ? 'Windows' : 'Other';
722
778
 
723
- const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other';
779
+ const os = platform === 'win32' ? 'Windows' /* v8 ignore next */ : 'Other';
724
780
 
725
781
  // v8 ignore next 3
726
782
  if (platform === 'linux') {
@@ -739,6 +795,7 @@ function uncovered() {
739
795
  }
740
796
  /* node:coverage enable */
741
797
  ```
798
+ - 可以设置 `v8Ignore: false` 完全禁用基于注释的忽略机制。
742
799
 
743
800
  ## Multiprocessing Support
744
801
  > 多进程支持可以很好的解决异步并行的情况。所有的覆盖率数据会保存到`[outputDir]/.cache`,在报告生成之后,这些缓存数据会被清除。除非开启了[调试模式](#debug-for-coverage-and-sourcemap),或者使用了`raw`报告
@@ -800,6 +857,16 @@ npx mcr node ./test/specs/node.test.js -r v8,console-details --lcov
800
857
  mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js
801
858
  ```
802
859
 
860
+ - `--import <module>` / `--require <module>`: 通过 `NODE_OPTIONS` 把一个预加载模块传给子进程。常用于 TypeScript/JSX 运行时(`tsx`、`ts-node` 等),也可用于加载 `mcr.config.ts`。要求 Node.js `>= 18.19`
861
+ ```sh
862
+ mcr --import tsx node ./test.ts
863
+ ```
864
+
865
+ - `--env [path]`: 子进程启动前从 dotenv 文件加载环境变量(默认 `.env`)。依赖 `process.loadEnvFile`,Node.js `20.6` 起支持
866
+ ```sh
867
+ mcr --env .env.test node ./test.js
868
+ ```
869
+
803
870
  - 参见例子
804
871
  - [Mocha](#mocha)
805
872
  - [TypeScript](#typescript)
@@ -814,7 +881,12 @@ mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js
814
881
  - `mcr.config.cjs`
815
882
  - `mcr.config.mjs`
816
883
  - `mcr.config.json` - json format
817
- - `mcr.config.ts` (requires preloading the ts execution module)
884
+ - `mcr.config.ts` (需要预加载 TypeScript 执行模块,比如 `tsx`):
885
+ ```sh
886
+ mcr --import tsx -c mcr.config.ts node ./test.js
887
+ ```
888
+
889
+ > 未指定自定义路径时,MCR 会从当前工作目录向上查找默认配置文件(通过 [`find-up`](https://github.com/sindresorhus/find-up))。不在搜索路径内的文件会被忽略
818
890
 
819
891
  ## Merge Coverage Reports
820
892
  以下这些使用场景可能需要使用合并覆盖率报告:
@@ -892,7 +964,7 @@ const coverageOptions = {
892
964
  ],
893
965
 
894
966
  onEnd: () => {
895
- // remove the raw files if it useless
967
+ // remove the raw files if no longer needed
896
968
  // inputDir.forEach((p) => {
897
969
  // fs.rmSync(p, {
898
970
  // recursive: true,
package/lib/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const path = require('path');
4
+ const { pathToFileURL } = require('url');
4
5
  const EC = require('eight-colors');
5
6
 
6
7
  const { program } = require('commander');
@@ -11,12 +12,18 @@ const Util = require('./utils/util.js');
11
12
 
12
13
  const version = require('../package.json').version;
13
14
 
14
- const getRegisterPath = (filename) => {
15
- const rel = Util.relativePath(path.resolve(__dirname, 'register', filename));
16
- if (rel.startsWith('.')) {
17
- return rel;
18
- }
19
- return `./${rel}`;
15
+ // quote NODE_OPTIONS argument if it contains whitespace so child processes
16
+ // inheriting the env var can parse it correctly
17
+ const quoteNodeOption = (v) => ((/\s/).test(v) ? `"${v}"` : v);
18
+
19
+ // absolute path so NODE_OPTIONS keeps resolving when child processes are
20
+ // spawned with a different cwd than the mcr parent process
21
+ const getRequirePath = () => {
22
+ return quoteNodeOption(path.resolve(__dirname, 'register', 'register.js'));
23
+ };
24
+
25
+ const getImportPath = () => {
26
+ return quoteNodeOption(pathToFileURL(path.resolve(__dirname, 'register', 'register.mjs')).href);
20
27
  };
21
28
 
22
29
  const getInitNodeOptions = async (cliOptions) => {
@@ -92,10 +99,10 @@ const initNodeOptions = async (cliOptions) => {
92
99
 
93
100
  // export source after
94
101
  if (preloadType === '--import') {
95
- const importPath = getRegisterPath('register.mjs');
102
+ const importPath = getImportPath();
96
103
  nodeOptions.unshift(`--import ${importPath}`);
97
104
  } else {
98
- const requirePath = getRegisterPath('register.js');
105
+ const requirePath = getRequirePath();
99
106
  nodeOptions.unshift(`--require ${requirePath}`);
100
107
  }
101
108
 
@@ -183,6 +190,7 @@ const executeCommand = async (command, cliOptions) => {
183
190
  process.on('uncaughtException', function(err) {
184
191
  Util.logError(`Process uncaughtException: ${err.message}`);
185
192
  console.log(err.stack);
193
+ process.exit(1);
186
194
  });
187
195
 
188
196
  // the -- separator
package/lib/index.d.ts CHANGED
@@ -36,7 +36,7 @@ declare namespace MCR {
36
36
  export type Watermarks = [number, number] | {
37
37
  /** V8 only */
38
38
  bytes?: [number, number];
39
- statements: [number, number];
39
+ statements?: [number, number];
40
40
  branches?: [number, number];
41
41
  functions?: [number, number];
42
42
  lines?: [number, number];
@@ -134,7 +134,7 @@ declare namespace MCR {
134
134
  } | ((file: CoverageFile) => boolean);
135
135
  }] |
136
136
  ['markdown-summary'] | ['markdown-summary', {
137
- color: 'unicode' | 'html' | 'tex' | string;
137
+ color?: 'unicode' | 'html' | 'tex' | string;
138
138
  metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">;
139
139
  /**
140
140
  * defaults to `coverage-summary.md`
@@ -143,7 +143,7 @@ declare namespace MCR {
143
143
  }] |
144
144
  ['markdown-details'] | ['markdown-details', {
145
145
  baseUrl?: string;
146
- color: 'unicode' | 'html' | 'tex' | string;
146
+ color?: 'unicode' | 'html' | 'tex' | string;
147
147
  maxCols?: number;
148
148
  skipPercent?: number;
149
149
  metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">;
@@ -207,7 +207,7 @@ declare namespace MCR {
207
207
  */
208
208
  none?: boolean;
209
209
  /** function only, function name */
210
- name?: boolean;
210
+ name?: string;
211
211
  }
212
212
 
213
213
  export interface IgnoredRange {
@@ -422,10 +422,10 @@ declare namespace MCR {
422
422
  sourceMapResolver?: (url: string, defaultResolver: Function) => Promise<any>;
423
423
 
424
424
  /** (V8 only) {function} onEntry hook */
425
- onEntry?: (entry: V8CoverageEntry) => Promise<void>;
425
+ onEntry?: (entry: V8CoverageEntry) => void | Promise<void>;
426
426
 
427
427
  /** {function} onEnd hook */
428
- onEnd?: (coverageResults: CoverageResults | undefined) => Promise<void>;
428
+ onEnd?: (coverageResults: CoverageResults | undefined) => void | Promise<void>;
429
429
 
430
430
  [key: string]: any;
431
431
  }
@@ -433,13 +433,13 @@ declare namespace MCR {
433
433
  export interface McrCliOptions extends CoverageReportOptions {
434
434
 
435
435
  /** (CLI only) {function} onStart hook */
436
- onStart?: (coverageReport: CoverageReport) => Promise<void>;
436
+ onStart?: (coverageReport: CoverageReport) => void | Promise<void>;
437
437
 
438
438
  /** (CLI only) {function} onReady hook before adding coverage data.
439
- *
439
+ *
440
440
  * Sometimes, the child process has not yet finished writing the coverage data, and it needs to wait here.
441
441
  */
442
- onReady?: (coverageReport: CoverageReport, nodeV8CoverageDir: string, subprocess: any) => Promise<void>;
442
+ onReady?: (coverageReport: CoverageReport, nodeV8CoverageDir: string, subprocess: any) => void | Promise<void>;
443
443
 
444
444
  }
445
445