monocart-coverage-reports 2.7.2 → 2.7.3

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
@@ -312,20 +312,26 @@ Options:
312
312
  --inline inline html for v8 report
313
313
  --assetsPath <path> assets path if not inline
314
314
  --lcov generate lcov.info file
315
+ --import <module> preload module at startup
316
+ --require <module> preload module at startup
315
317
  -h, --help display help for command
316
318
  ```
317
319
 
318
320
  - Loading config file by priority:
319
- - custom config file with `-c` or `--config`
321
+ - Custom config file with `-c` or `--config`
320
322
  - `mcr.config.js`
321
323
  - `mcr.config.cjs`
322
324
  - `mcr.config.mjs`
323
325
  - `mcr.config.json` - json format
326
+ - `mcr.config.ts` (requires preloading the ts execution module)
324
327
  - `.mcrrc.js`
325
328
  - `.mcrrc` - json format
326
- - `mcr.config.ts` (requires preloading the typescript module)
327
329
 
328
330
  - Working with `tsx`, see [mcr-tsx](https://github.com/cenfun/mcr-tsx)
331
+ ```sh
332
+ npx mcr --import tsx tsx ./src/example.ts
333
+ ```
334
+
329
335
  - Working with `ts-node`, see [mcr-ts-node](https://github.com/cenfun/mcr-ts-node)
330
336
 
331
337
  ## Compare Reports
package/lib/cli.js CHANGED
@@ -152,7 +152,7 @@ const executeCommand = async (command, cliOptions) => {
152
152
  };
153
153
 
154
154
  process.on('uncaughtException', function(err) {
155
- Util.logError(`ERROR: ${err.message || err}`);
155
+ Util.logError(`Process uncaughtException: ${err.message || err}`);
156
156
  });
157
157
 
158
158
  program
@@ -128,6 +128,17 @@ const saveSourceFile = async (filePath, data) => {
128
128
 
129
129
  };
130
130
 
131
+ const getInlineSourceMap = (content) => {
132
+ let smc;
133
+ try {
134
+ smc = convertSourceMap.fromSource(content);
135
+ } catch (e) {
136
+ // ignore "//# sourceMappingURL=" in a string
137
+ // console.log(e);
138
+ }
139
+ return smc;
140
+ };
141
+
131
142
  const collectSourceMaps = async (v8list, options) => {
132
143
 
133
144
  const smList = [];
@@ -166,7 +177,7 @@ const collectSourceMaps = async (v8list, options) => {
166
177
  // check sourceMap only for js
167
178
  if (type === 'js' && !sourceData.sourceMap) {
168
179
  // from inline sync
169
- const smc = convertSourceMap.fromSource(source);
180
+ const smc = getInlineSourceMap(source);
170
181
  if (smc) {
171
182
  sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
172
183
  smList.push({
@@ -129,13 +129,18 @@ const getComparedPosition = (info, direction) => {
129
129
  gt = gt.trimEnd();
130
130
  ot = ot.trimEnd();
131
131
 
132
- // no content after trim
133
- if (!ot.length) {
132
+ // no original content after trim
133
+ if (!ot) {
134
134
  return {
135
135
  pos: direction === 'start' ? oLen : 0
136
136
  };
137
137
  }
138
138
 
139
+ // no generated content after trim
140
+ if (!gt) {
141
+ return;
142
+ }
143
+
139
144
  // same content
140
145
  if (gt === ot) {
141
146
  return {
@@ -273,16 +278,16 @@ const getFixedPosition = (info, direction) => {
273
278
 
274
279
  // ========================================================================================================
275
280
 
276
- const getOriginalEndOffset = (m, rangeInfo) => {
281
+ const getOriginalEndOffset = (m, cache) => {
277
282
  if (!m.originalEndOffset) {
278
- const line = rangeInfo.originalState.locator.getLine(m.originalLine + 1);
283
+ const line = cache.originalState.locator.getLine(m.originalLine + 1);
279
284
  m.originalEndOffset = line ? line.end : m.originalOffset;
280
285
  }
281
286
  return m.originalEndOffset;
282
287
  };
283
288
 
284
- const getOriginalText = (m1, m2, rangeInfo) => {
285
- const originalLocator = rangeInfo.originalState.locator;
289
+ const getOriginalText = (m1, m2, cache) => {
290
+ const originalLocator = cache.originalState.locator;
286
291
 
287
292
  const o1 = m1.originalOffset;
288
293
  const o2 = m2.originalOffset;
@@ -299,7 +304,7 @@ const getOriginalText = (m1, m2, rangeInfo) => {
299
304
  // esbuild fixing two mapping have same original
300
305
  // m1 to end line
301
306
  if (o1 === o2) {
302
- const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
307
+ const originalEndOffset = getOriginalEndOffset(m1, cache);
303
308
  return {
304
309
  originalOffset: o1,
305
310
  originalText: originalLocator.getSlice(o1, originalEndOffset)
@@ -319,12 +324,12 @@ const getOriginalText = (m1, m2, rangeInfo) => {
319
324
 
320
325
  // if (direction === 'start') {
321
326
  // should be m2 ?
322
- // console.log(direction, rangeInfo.originalState.sourcePath);
327
+ // console.log(direction, cache.originalState.sourcePath);
323
328
  // console.log(m1, m2);
324
329
  // }
325
330
 
326
331
  // should be wrong, ignore m2
327
- const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
332
+ const originalEndOffset = getOriginalEndOffset(m1, cache);
328
333
  return {
329
334
  originalOffset: o1,
330
335
  originalText: originalLocator.getSlice(o1, originalEndOffset)
@@ -385,10 +390,10 @@ const getGeneratedText = (m1, m2, state, offset) => {
385
390
 
386
391
  // ========================================================================================================
387
392
 
388
- const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
393
+ const getFixedOriginalStart = (start, mappings, state, cache) => {
389
394
 
390
395
  const [m1, m2] = mappings;
391
- const { originalState, crossStart } = rangeInfo;
396
+ const { originalState, crossStart } = cache;
392
397
 
393
398
  // cross file from start of line
394
399
  if (crossStart) {
@@ -398,7 +403,7 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
398
403
  }
399
404
 
400
405
  const direction = 'start';
401
- const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo);
406
+ const { originalText, originalOffset } = getOriginalText(m1, m2, cache);
402
407
  const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start);
403
408
 
404
409
  const info = {
@@ -426,14 +431,14 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
426
431
  };
427
432
  };
428
433
 
429
- const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
434
+ const getFixedOriginalEnd = (end, mappings, state, cache) => {
430
435
 
431
436
  const [m1, m2] = mappings;
432
- const { originalState, crossEnd } = rangeInfo;
437
+ const { originalState, crossEnd } = cache;
433
438
 
434
439
  // cross file until e1 line end (not file end)
435
440
  if (crossEnd) {
436
- const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
441
+ const originalEndOffset = getOriginalEndOffset(m1, cache);
437
442
  return {
438
443
  originalEnd: originalEndOffset
439
444
  };
@@ -448,33 +453,8 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
448
453
  };
449
454
  }
450
455
 
451
- // quick check next one if exact match
452
- // most of case is same string
453
- if (m2.generatedOffset === end + 1) {
454
- const gt = state.locator.source[end];
455
- const oi = m2.originalOffset - 1;
456
- const ot = originalState.locator.source[oi];
457
- // it could be ; but it quite far away
458
- if (gt === ot && [';', ','].includes(gt)) {
459
- return {
460
- originalEnd: oi
461
- };
462
- }
463
-
464
- // Not applicable
465
- // console.log('==================================');
466
- // console.log({
467
- // gp: state.sourcePath,
468
- // g: end,
469
- // gt,
470
- // op: originalState.sourcePath,
471
- // o: oi,
472
- // ot
473
- // });
474
- }
475
-
476
456
  const direction = 'end';
477
- const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo);
457
+ const { originalText, originalOffset } = getOriginalText(m1, m2, cache);
478
458
  const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
479
459
 
480
460
  const info = {
@@ -506,23 +486,57 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
506
486
 
507
487
  // ========================================================================================================
508
488
 
509
- const getOriginalStart = (start, startMapping, state, rangeInfo) => {
510
- if (Array.isArray(startMapping)) {
511
- return getFixedOriginalStart(start, startMapping, state, rangeInfo);
489
+ const getOriginalStartPosition = (cache, state) => {
490
+
491
+ const { start, startMappings } = cache;
492
+
493
+ if (Array.isArray(startMappings)) {
494
+ return getFixedOriginalStart(start, startMappings, state, cache);
512
495
  }
496
+
513
497
  // Exact match
514
498
  return {
515
- originalStart: startMapping.originalOffset
499
+ originalStart: startMappings.originalOffset
516
500
  };
517
501
  };
518
502
 
519
- const getOriginalEnd = (end, endMapping, state, rangeInfo) => {
520
- if (Array.isArray(endMapping)) {
521
- return getFixedOriginalEnd(end, endMapping, state, rangeInfo);
503
+ const getOriginalExclusiveEnd = (cache, state) => {
504
+ // end, exclusive mappings
505
+ const { end } = cache;
506
+ const { decodedMappings } = state;
507
+ const endMappings = findMapping(decodedMappings, end);
508
+ if (Array.isArray(endMappings)) {
509
+ return getFixedOriginalEnd(end, endMappings, state, cache);
522
510
  }
523
- // Exact match
511
+
512
+ // Exact match end
524
513
  return {
525
- originalEnd: endMapping.originalOffset
514
+ originalEnd: endMappings.originalOffset
515
+ };
516
+ };
517
+
518
+ const getOriginalEndPosition = (cache, state) => {
519
+
520
+ const { endMappings, originalState } = cache;
521
+
522
+ // (end - 1), inclusive
523
+ if (Array.isArray(endMappings)) {
524
+ return getOriginalExclusiveEnd(cache, state);
525
+ }
526
+
527
+ // Exact match (end - 1)
528
+
529
+ // check end char
530
+ const oi = endMappings.originalOffset;
531
+ const originalEndChar = originalState.locator.getSlice(oi, oi + 1);
532
+ // the char should never end with "{" or "("
533
+ if (['{', '('].includes(originalEndChar)) {
534
+ return getOriginalExclusiveEnd(cache, state);
535
+ }
536
+
537
+ // inclusive to exclusive
538
+ return {
539
+ originalEnd: oi + 1
526
540
  };
527
541
  };
528
542
 
@@ -536,9 +550,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
536
550
  sourceIndex: s1
537
551
  };
538
552
  }
539
- return {
540
- error: true
541
- };
542
553
  };
543
554
 
544
555
  const checkIndex21 = (s1, s2, e1) => {
@@ -553,9 +564,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
553
564
  sourceIndex: e1
554
565
  };
555
566
  }
556
- return {
557
- error: true
558
- };
559
567
  };
560
568
 
561
569
  const checkIndex12 = (s1, e1, e2) => {
@@ -570,9 +578,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
570
578
  sourceIndex: s1
571
579
  };
572
580
  }
573
- return {
574
- error: true
575
- };
576
581
  };
577
582
 
578
583
  const checkIndex22 = (s1, s2, e1, e2) => {
@@ -602,10 +607,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
602
607
  // both between two mappings: 38,39 ~ 38,39
603
608
  // if (s1 === e1 && s2 === e2) {
604
609
  // }
605
-
606
- return {
607
- error: true
608
- };
609
610
  };
610
611
 
611
612
  // both exact matched
@@ -626,13 +627,20 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
626
627
 
627
628
  };
628
629
 
629
- const getOriginalState = (startMappings, endMappings, originalMap) => {
630
+ const getOriginalState = (start, end, state, originalMap) => {
631
+
632
+ const mappingInfo = getMappingInfo(start, end, state);
633
+ if (mappingInfo.error) {
634
+ return mappingInfo;
635
+ }
636
+
637
+ const { startMappings, endMappings } = mappingInfo;
630
638
 
631
639
  // check source file indexes
632
640
  const startIndexes = [].concat(startMappings).map((it) => it.sourceIndex);
633
641
  const endIndexes = [].concat(endMappings).map((it) => it.sourceIndex);
634
- const rangeInfo = checkSourceFileIndexes(startIndexes, endIndexes);
635
- if (rangeInfo.error) {
642
+ const results = checkSourceFileIndexes(startIndexes, endIndexes);
643
+ if (!results) {
636
644
  return {
637
645
  error: true,
638
646
  errors: [`invalid source indexes: ${EC.yellow(`${startIndexes} ~ ${endIndexes}`)}`]
@@ -641,7 +649,7 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
641
649
 
642
650
  const {
643
651
  sourceIndex, crossStart, crossEnd
644
- } = rangeInfo;
652
+ } = results;
645
653
 
646
654
  // if (crossStart || crossEnd) {
647
655
  // console.log(EC.magenta('cross file'), EC.yellow(`${startIndexes} ~ ${endIndexes}`));
@@ -655,11 +663,17 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
655
663
  };
656
664
  }
657
665
 
666
+ // cache for original info
658
667
  return {
659
668
  // for debug
660
669
  // startIndexes,
661
670
  // endIndexes,
662
671
 
672
+ start,
673
+ end,
674
+ startMappings,
675
+ endMappings,
676
+
663
677
  sourceIndex,
664
678
  crossStart,
665
679
  crossEnd,
@@ -667,7 +681,9 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
667
681
  };
668
682
  };
669
683
 
670
- const getMappingInfo = (decodedMappings, start, end) => {
684
+ const getMappingInfo = (start, end, state) => {
685
+
686
+ const { decodedMappings } = state;
671
687
  // possible no length
672
688
  if (decodedMappings.length < 2) {
673
689
  return {
@@ -677,9 +693,6 @@ const getMappingInfo = (decodedMappings, start, end) => {
677
693
  }
678
694
 
679
695
  // start: inclusive
680
- // end: exclusive
681
- // could be 4 mappings found
682
-
683
696
  const startMappings = findMapping(decodedMappings, start);
684
697
  if (!startMappings) {
685
698
  return {
@@ -688,7 +701,8 @@ const getMappingInfo = (decodedMappings, start, end) => {
688
701
  };
689
702
  }
690
703
 
691
- const endMappings = findMapping(decodedMappings, end);
704
+ // end: exclusive
705
+ const endMappings = findMapping(decodedMappings, end - 1);
692
706
  if (!endMappings) {
693
707
  return {
694
708
  error: true,
@@ -696,6 +710,7 @@ const getMappingInfo = (decodedMappings, start, end) => {
696
710
  };
697
711
  }
698
712
 
713
+ // could be 4 mappings found
699
714
  return {
700
715
  startMappings,
701
716
  endMappings
@@ -704,7 +719,7 @@ const getMappingInfo = (decodedMappings, start, end) => {
704
719
 
705
720
  const findOriginalRange = (start, end, state, originalMap) => {
706
721
 
707
- const { sourcePath, decodedMappings } = state;
722
+ const { sourcePath } = state;
708
723
 
709
724
  const createMappingError = (errors) => {
710
725
  return {
@@ -716,29 +731,17 @@ const findOriginalRange = (start, end, state, originalMap) => {
716
731
  };
717
732
  };
718
733
 
719
- const mappingInfo = getMappingInfo(decodedMappings, start, end);
720
- if (mappingInfo.error) {
721
- return createMappingError(mappingInfo.errors);
722
- }
723
-
724
- const { startMappings, endMappings } = mappingInfo;
725
-
726
- const rangeInfo = getOriginalState(startMappings, endMappings, originalMap);
727
- if (rangeInfo.error) {
728
- return createMappingError(rangeInfo.errors);
729
- }
730
-
731
- const originalStartResult = getOriginalStart(start, startMappings, state, rangeInfo);
732
- if (originalStartResult.error) {
733
- return createMappingError(originalStartResult.errors);
734
- }
735
-
736
- const originalEndResult = getOriginalEnd(end, endMappings, state, rangeInfo);
737
- if (originalEndResult.error) {
738
- return createMappingError(originalEndResult.errors);
734
+ const cache = getOriginalState(start, end, state, originalMap);
735
+ if (cache.error) {
736
+ return createMappingError(cache.errors);
739
737
  }
740
738
 
739
+ const originalStartResult = getOriginalStartPosition(cache, state);
741
740
  const { originalStart } = originalStartResult;
741
+ // could be used for end
742
+ cache.originalStart = originalStart;
743
+
744
+ const originalEndResult = getOriginalEndPosition(cache, state);
742
745
  const { originalEnd } = originalEndResult;
743
746
 
744
747
  // range start > end
@@ -746,7 +749,7 @@ const findOriginalRange = (start, end, state, originalMap) => {
746
749
  return createMappingError([`invalid original start > end: ${EC.yellow(originalStart)} > ${EC.yellow(originalEnd)}`]);
747
750
  }
748
751
 
749
- const { originalState } = rangeInfo;
752
+ const { originalState } = cache;
750
753
 
751
754
  return {
752
755
  start: originalStart,
package/lib/index.js CHANGED
@@ -28,12 +28,15 @@ const resolveConfigOptions = async (configPath) => {
28
28
  err = ee;
29
29
  }
30
30
 
31
- if (err || !configOptions) {
31
+ if (err) {
32
32
  Util.logError(`ERROR: failed to load config "${configPath}": ${err && err.message} `);
33
33
  return;
34
34
  }
35
35
 
36
- configOptions = configOptions.default || configOptions;
36
+ // could be multiple level default
37
+ while (configOptions && configOptions.default) {
38
+ configOptions = configOptions.default;
39
+ }
37
40
 
38
41
  return configOptions;
39
42
  };
@@ -237,9 +240,9 @@ class CoverageReport {
237
240
  'mcr.config.cjs',
238
241
  'mcr.config.mjs',
239
242
  'mcr.config.json',
243
+ 'mcr.config.ts',
240
244
  '.mcrrc.js',
241
- '.mcrrc',
242
- 'mcr.config.ts'
245
+ '.mcrrc'
243
246
  ];
244
247
 
245
248
  const existsList = configList.filter((p) => p && fs.existsSync(p));
@@ -262,7 +265,8 @@ class CoverageReport {
262
265
  return;
263
266
  }
264
267
 
265
- Util.logInfo(`Loaded config: ${EC.cyan(configPath)}`);
268
+ Util.logInfo(`Loaded: ${EC.cyan(configPath)}`);
269
+
266
270
  // init options again
267
271
  this.options = {
268
272
  ... defaultOptions,
@@ -3,35 +3,53 @@ const path = require('path');
3
3
  const Util = require('../utils/util.js');
4
4
  const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
5
5
 
6
- async function load(url, context, nextLoad) {
7
-
8
- const loaded = await nextLoad(url, context);
9
- const { source, format } = loaded;
10
- const dir = process.env.NODE_V8_COVERAGE;
6
+ function saveFile(url, source, dir) {
7
+ if (!fs.existsSync(dir)) {
8
+ fs.mkdirSync(dir, {
9
+ recursive: true
10
+ });
11
+ }
11
12
 
12
- if (dir && typeof source === 'string' && (format === 'module' || format === 'commonjs')) {
13
+ const id = Util.calculateSha1(url + source);
14
+ const filePath = path.resolve(dir, `source-${id}.json`);
15
+ if (!fs.existsSync(filePath)) {
16
+ fs.writeFileSync(filePath, JSON.stringify({
17
+ url,
18
+ source
19
+ }));
20
+ }
13
21
 
14
- if (convertSourceMap.mapFileCommentRegex.test(source)) {
22
+ }
15
23
 
16
- if (!fs.existsSync(dir)) {
17
- fs.mkdirSync(dir, {
18
- recursive: true
19
- });
20
- }
24
+ function saveSource(url, loaded, dir) {
21
25
 
22
- const id = Util.calculateSha1(url + source);
23
- const filePath = path.resolve(dir, `source-${id}.json`);
24
- if (!fs.existsSync(filePath)) {
25
- fs.writeFileSync(filePath, JSON.stringify({
26
- url,
27
- source
28
- }));
29
- }
26
+ // filter node modules
27
+ if (url.startsWith('node:')) {
28
+ return;
29
+ }
30
30
 
31
- }
31
+ const { source, format } = loaded;
32
+ if (typeof source !== 'string' || !['module', 'commonjs'].includes(format)) {
33
+ // no source or wrong format
34
+ return;
35
+ }
32
36
 
37
+ if (!convertSourceMap.mapFileCommentRegex.test(source)) {
38
+ // no sourcemap
39
+ return;
33
40
  }
34
41
 
42
+ saveFile(url, source, dir);
43
+
44
+ }
45
+
46
+ async function load(url, context, nextLoad) {
47
+ const loaded = await nextLoad(url, context);
48
+ const dir = process.env.NODE_V8_COVERAGE;
49
+ if (dir) {
50
+ // only for coverage enabled
51
+ saveSource(url, loaded, dir);
52
+ }
35
53
  return loaded;
36
54
  }
37
55
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "2.7.2",
3
+ "version": "2.7.3",
4
4
  "description": "A code coverage tool to generate native V8 reports or Istanbul reports.",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -27,25 +27,30 @@
27
27
  "build-docs": "node ./scripts/build-docs.js",
28
28
  "build-test": "node ./scripts/build-test.js",
29
29
  "build": "sf lint && sf b -p && npm run build-test",
30
- "test-node": "npm run test-node-env && npm run test-node-api && npm run test-node-ins && npm run test-node-cdp && npm run test-node-koa && npm run test-node-vm",
31
30
  "test-node-env": "cross-env NODE_V8_COVERAGE=.temp/v8-coverage-env node ./test/test-node-env.js && node ./test/generate-report.js",
32
31
  "test-node-api": "cross-env NODE_V8_COVERAGE=.temp/v8-coverage-api node ./test/test-node-api.js",
33
- "test-node-fgc": "node ./test/test-node-fgc.js",
34
32
  "test-node-ins": "node ./test/test-node-ins.js",
35
33
  "test-node-cdp": "node --inspect=9229 ./test/test-node-cdp.js",
36
- "test-node-koa": "node ./test/test-node-koa.js",
37
34
  "test-node-vm": "node ./test/test-node-vm.js",
35
+ "test-node-koa": "node ./test/test-node-koa.js",
36
+ "test-node-fgc": "node ./test/test-node-fgc.js",
37
+ "test-node": "npm run test-node-env && npm run test-node-api && npm run test-node-ins && npm run test-node-cdp && npm run test-node-vm && npm run test-node-koa",
38
38
  "test-istanbul": "node ./test/test-istanbul.js",
39
39
  "test-v8": "node ./test/test-v8.js",
40
40
  "test-puppeteer": "node ./test/test-puppeteer.js",
41
- "test-browser": "node ./test/test-browser.js && npm run test-istanbul && npm run test-v8 && npm run test-puppeteer && npm run test-anonymous && npm run test-css",
42
41
  "test-anonymous": "node ./test/test-anonymous.js",
43
42
  "test-css": "node ./test/test-css.js",
44
- "test-client": "node ./test/test-client.js",
43
+ "test-minify": "node ./test/test-minify.js",
44
+ "test-esbuild": "node ./test/test-esbuild.js",
45
+ "test-rollup": "node ./test/test-rollup.js",
46
+ "test-v8-and-istanbul": "node ./test/test-v8-and-istanbul.js",
47
+ "test-browser": "npm run test-istanbul && npm run test-v8 && npm run test-puppeteer && npm run test-anonymous && npm run test-css && npm run test-minify && npm run test-esbuild && npm run test-rollup && npm run test-v8-and-istanbul",
45
48
  "test-cli": "npx mcr node ./test/specs/node.test.js -c test/mcr.config.cli.js",
49
+ "test-tsx": "npx mcr tsx ./test/specs/tsx.test.ts -c test/mcr.config.tsx.js",
46
50
  "test-merge": "node ./test/test-merge.js",
47
51
  "test-merge-istanbul": "node ./test/test-merge-istanbul.js",
48
- "test-all": "npm run test-browser && npm run test-node && npm run test-cli && npm run test-merge && npm run build-docs",
52
+ "test-client": "node ./test/test-client.js",
53
+ "test-all": "npm run test-node && npm run test-browser && npm run test-cli && npm run test-tsx && npm run test-merge && npm run build-docs",
49
54
  "test": "npx mcr npm run test-all -c test/mcr.config.mcr.js",
50
55
  "test:snap": "cross-env TEST_SNAPSHOT=true npm run test",
51
56
  "dev": "sf d v8",
@@ -77,6 +82,7 @@
77
82
  },
78
83
  "devDependencies": {
79
84
  "commander": "^12.0.0",
85
+ "esbuild": "^0.20.2",
80
86
  "eslint": "^8.57.0",
81
87
  "eslint-config-plus": "^1.0.6",
82
88
  "eslint-plugin-html": "^8.0.0",