monocart-coverage-reports 2.5.9 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +791 -778
- package/lib/cli.js +250 -215
- package/lib/converter/ast-visitor.js +675 -666
- package/lib/converter/ast.js +353 -353
- package/lib/converter/collect-source-maps.js +201 -201
- package/lib/converter/converter.js +1487 -1429
- package/lib/converter/find-original-range.js +737 -737
- package/lib/converter/ignore.js +163 -163
- package/lib/converter/info-branch.js +93 -93
- package/lib/converter/info-function.js +63 -63
- package/lib/converter/info-statement.js +43 -43
- package/lib/default/options.js +84 -84
- package/lib/default/template.html +47 -47
- package/lib/generate.js +720 -532
- package/lib/index.d.ts +360 -324
- package/lib/index.js +187 -180
- package/lib/index.mjs +5 -3
- package/lib/istanbul/istanbul-summary.js +70 -63
- package/lib/istanbul/istanbul.js +146 -146
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/concurrency.js +74 -74
- package/lib/platform/share.js +484 -484
- package/lib/utils/dedupe.js +118 -118
- package/lib/utils/request.js +62 -62
- package/lib/utils/snapshot.js +381 -0
- package/lib/utils/source-path.js +179 -179
- package/lib/utils/util.js +526 -526
- package/lib/v8/v8-summary.js +138 -138
- package/lib/v8/v8.js +400 -630
- package/package.json +81 -80
package/lib/cli.js
CHANGED
|
@@ -1,216 +1,251 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const EC = require('eight-colors');
|
|
6
|
-
const { fileURLToPath, pathToFileURL } = require('url');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'
|
|
28
|
-
'mcr.config.
|
|
29
|
-
'mcr.config.
|
|
30
|
-
'mcr.config.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
...
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const EC = require('eight-colors');
|
|
6
|
+
const { fileURLToPath, pathToFileURL } = require('url');
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
foregroundChild,
|
|
10
|
+
program
|
|
11
|
+
} = require('./packages/monocart-coverage-vendor.js');
|
|
12
|
+
|
|
13
|
+
const MCR = require('./index.js');
|
|
14
|
+
const Util = require('./utils/util.js');
|
|
15
|
+
const defaultOptions = require('./default/options.js');
|
|
16
|
+
const { resolveSourceMap } = require('./converter/collect-source-maps.js');
|
|
17
|
+
|
|
18
|
+
const version = require('../package.json').version;
|
|
19
|
+
|
|
20
|
+
const cleanDir = (dir) => {
|
|
21
|
+
Util.rmSync(dir);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const resolveConfigPath = (customConfigPath) => {
|
|
25
|
+
|
|
26
|
+
const configList = [
|
|
27
|
+
'.mcrrc',
|
|
28
|
+
'mcr.config.json',
|
|
29
|
+
'mcr.config.mjs',
|
|
30
|
+
'mcr.config.cjs',
|
|
31
|
+
'mcr.config.js'
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
if (customConfigPath) {
|
|
35
|
+
configList.push(customConfigPath);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const existsList = configList.filter((p) => fs.existsSync(p));
|
|
39
|
+
if (!existsList.length) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// last one
|
|
44
|
+
const configPath = existsList.pop();
|
|
45
|
+
Util.logInfo(`Config: ${EC.cyan(configPath)}`);
|
|
46
|
+
|
|
47
|
+
return configPath;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const resolveConfigOptions = async (configPath) => {
|
|
51
|
+
|
|
52
|
+
// json format
|
|
53
|
+
const ext = path.extname(configPath);
|
|
54
|
+
if (ext === '.json' || configPath.slice(-2) === 'rc') {
|
|
55
|
+
return JSON.parse(Util.readFileSync(configPath));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let configOptions;
|
|
59
|
+
let err;
|
|
60
|
+
try {
|
|
61
|
+
configOptions = await import(pathToFileURL(configPath));
|
|
62
|
+
} catch (ee) {
|
|
63
|
+
err = ee;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!configOptions) {
|
|
67
|
+
Util.logError(`ERROR: failed to import "${configPath}" ${err.message} `);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
configOptions = configOptions.default || configOptions;
|
|
72
|
+
|
|
73
|
+
return configOptions;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const initOptions = async (cliOptions) => {
|
|
77
|
+
|
|
78
|
+
const configPath = resolveConfigPath(cliOptions.config);
|
|
79
|
+
if (configPath) {
|
|
80
|
+
const configOptions = await resolveConfigOptions(configPath);
|
|
81
|
+
if (configOptions) {
|
|
82
|
+
cliOptions = {
|
|
83
|
+
... configOptions,
|
|
84
|
+
... cliOptions
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// report options
|
|
90
|
+
const options = {
|
|
91
|
+
... defaultOptions
|
|
92
|
+
};
|
|
93
|
+
Object.keys(cliOptions).forEach((k) => {
|
|
94
|
+
if (Util.hasOwn(options, k)) {
|
|
95
|
+
options[k] = cliOptions[k];
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return options;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const resolveEntrySource = (entry, sourceMapCache = {}) => {
|
|
103
|
+
let source;
|
|
104
|
+
const filePath = fileURLToPath(entry.url);
|
|
105
|
+
const extname = path.extname(filePath);
|
|
106
|
+
if (fs.existsSync(filePath)) {
|
|
107
|
+
source = fs.readFileSync(filePath).toString('utf8');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// not for typescript
|
|
111
|
+
if (source && !['.ts', '.tsx'].includes(extname)) {
|
|
112
|
+
entry.source = source;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const sourcemapData = sourceMapCache[entry.url];
|
|
117
|
+
const lineLengths = sourcemapData && sourcemapData.lineLengths;
|
|
118
|
+
|
|
119
|
+
// for fake source file (can not parse to AST)
|
|
120
|
+
if (lineLengths) {
|
|
121
|
+
// get runtime code with ts-node
|
|
122
|
+
let fakeSource = '';
|
|
123
|
+
sourcemapData.lineLengths.forEach((length) => {
|
|
124
|
+
fakeSource += `${''.padEnd(length, '*')}\n`;
|
|
125
|
+
});
|
|
126
|
+
entry.fake = true;
|
|
127
|
+
entry.source = fakeSource;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Note: no runtime code in source map cache
|
|
131
|
+
// This is a problem for typescript
|
|
132
|
+
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const resolveEntrySourceMap = (entry, sourceMapCache = {}) => {
|
|
136
|
+
// sourcemap data
|
|
137
|
+
const sourcemapData = sourceMapCache[entry.url];
|
|
138
|
+
if (sourcemapData) {
|
|
139
|
+
if (sourcemapData.data) {
|
|
140
|
+
entry.sourceMap = resolveSourceMap(sourcemapData.data, entry.url);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const collectCoverageData = (coverageList, entryFilterHandler, sourceMapCache = {}) => {
|
|
146
|
+
|
|
147
|
+
if (!Util.isList(coverageList)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// filter node internal files
|
|
152
|
+
coverageList = coverageList.filter((entry) => entry.url && entry.url.startsWith('file:'));
|
|
153
|
+
coverageList = coverageList.filter(entryFilterHandler);
|
|
154
|
+
|
|
155
|
+
if (!Util.isList(coverageList)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const entry of coverageList) {
|
|
160
|
+
resolveEntrySource(entry, sourceMapCache);
|
|
161
|
+
resolveEntrySourceMap(entry, sourceMapCache);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return coverageList;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const executeCommand = async (command, cliOptions) => {
|
|
168
|
+
|
|
169
|
+
const options = await initOptions(cliOptions);
|
|
170
|
+
|
|
171
|
+
Util.logInfo(`Execute: ${EC.cyan(command)}`);
|
|
172
|
+
// console.log(options);
|
|
173
|
+
|
|
174
|
+
const nodeV8CoverageDir = path.resolve(options.outputDir, '.v8-coverage');
|
|
175
|
+
process.env.NODE_V8_COVERAGE = nodeV8CoverageDir;
|
|
176
|
+
|
|
177
|
+
cleanDir(nodeV8CoverageDir);
|
|
178
|
+
|
|
179
|
+
// console.log('nodeV8CoverageDir', nodeV8CoverageDir);
|
|
180
|
+
|
|
181
|
+
const coverageReport = MCR(options);
|
|
182
|
+
coverageReport.cleanCache();
|
|
183
|
+
|
|
184
|
+
// on start hook
|
|
185
|
+
const onStart = cliOptions.onStart;
|
|
186
|
+
if (typeof onStart === 'function') {
|
|
187
|
+
await onStart(coverageReport);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
foregroundChild(command, {
|
|
191
|
+
shell: true
|
|
192
|
+
}, async () => {
|
|
193
|
+
|
|
194
|
+
if (!fs.existsSync(nodeV8CoverageDir)) {
|
|
195
|
+
EC.logRed(`Not found coverage data: ${Util.relativePath(nodeV8CoverageDir)}`);
|
|
196
|
+
return 1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const entryFilterHandler = coverageReport.getEntryFilter();
|
|
200
|
+
|
|
201
|
+
const files = fs.readdirSync(nodeV8CoverageDir);
|
|
202
|
+
for (const filename of files) {
|
|
203
|
+
const content = fs.readFileSync(path.resolve(nodeV8CoverageDir, filename)).toString('utf-8');
|
|
204
|
+
const json = JSON.parse(content);
|
|
205
|
+
const coverageList = json.result;
|
|
206
|
+
const sourceMapCache = json['source-map-cache'];
|
|
207
|
+
const coverageData = await collectCoverageData(coverageList, entryFilterHandler, sourceMapCache);
|
|
208
|
+
if (coverageData) {
|
|
209
|
+
await coverageReport.add(coverageData);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
await coverageReport.generate();
|
|
214
|
+
|
|
215
|
+
// remove nodeV8CoverageDir
|
|
216
|
+
if (options.logging !== 'debug') {
|
|
217
|
+
cleanDir(nodeV8CoverageDir);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return process.exitCode;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
program
|
|
226
|
+
.name('mcr')
|
|
227
|
+
.description('CLI to generate coverage reports')
|
|
228
|
+
.version(version)
|
|
229
|
+
.argument('<command>', 'command to execute')
|
|
230
|
+
.option('-c, --config <path>', 'custom config path')
|
|
231
|
+
.option('-o, --outputDir <dir>', 'output dir for reports')
|
|
232
|
+
.option('-r, --reports <name[,name]>', 'coverage reports to use')
|
|
233
|
+
.option('-n, --name <name>', 'report name for title')
|
|
234
|
+
.option('-i, --inputDir <dir>', 'input dir for merging raw files')
|
|
235
|
+
|
|
236
|
+
.option('--entryFilter <pattern>', 'entry url filter')
|
|
237
|
+
.option('--sourceFilter <pattern>', 'source path filter')
|
|
238
|
+
|
|
239
|
+
.option('--outputFile <path>', 'output file for v8 report')
|
|
240
|
+
.option('--inline', 'inline html for v8 report')
|
|
241
|
+
.option('--assetsPath <path>', 'assets path if not inline')
|
|
242
|
+
|
|
243
|
+
.option('--lcov', 'generate lcov.info file')
|
|
244
|
+
|
|
245
|
+
.option('--logging <logging>', 'off, error, info, debug')
|
|
246
|
+
|
|
247
|
+
.action((command, cliOptions) => {
|
|
248
|
+
executeCommand(command, cliOptions);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
program.parse();
|