modestbench 0.7.0 → 0.8.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/CHANGELOG.md +12 -0
- package/dist/cli/commands/run.cjs +89 -49
- package/dist/cli/commands/run.cjs.map +1 -1
- package/dist/cli/commands/run.d.cts.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +90 -50
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/constants.cjs +2 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +2 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/errors/index.cjs +3 -1
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +1 -1
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/reporter.cjs +45 -1
- package/dist/errors/reporter.cjs.map +1 -1
- package/dist/errors/reporter.d.cts +32 -0
- package/dist/errors/reporter.d.cts.map +1 -1
- package/dist/errors/reporter.d.ts +32 -0
- package/dist/errors/reporter.d.ts.map +1 -1
- package/dist/errors/reporter.js +42 -0
- package/dist/errors/reporter.js.map +1 -1
- package/dist/index.cjs +16 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/services/reporter-loader.cjs +281 -0
- package/dist/services/reporter-loader.cjs.map +1 -0
- package/dist/services/reporter-loader.d.cts +67 -0
- package/dist/services/reporter-loader.d.cts.map +1 -0
- package/dist/services/reporter-loader.d.ts +67 -0
- package/dist/services/reporter-loader.d.ts.map +1 -0
- package/dist/services/reporter-loader.js +241 -0
- package/dist/services/reporter-loader.js.map +1 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +1 -0
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/plugin.cjs +9 -0
- package/dist/types/plugin.cjs.map +1 -0
- package/dist/types/plugin.d.cts +179 -0
- package/dist/types/plugin.d.cts.map +1 -0
- package/dist/types/plugin.d.ts +179 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +8 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/utils/package.cjs +66 -5
- package/dist/utils/package.cjs.map +1 -1
- package/dist/utils/package.d.cts +6 -0
- package/dist/utils/package.d.cts.map +1 -1
- package/dist/utils/package.d.ts +6 -0
- package/dist/utils/package.d.ts.map +1 -1
- package/dist/utils/package.js +31 -1
- package/dist/utils/package.js.map +1 -1
- package/dist/utils/reporter-utils.cjs +90 -0
- package/dist/utils/reporter-utils.cjs.map +1 -0
- package/dist/utils/reporter-utils.d.cts +42 -0
- package/dist/utils/reporter-utils.d.cts.map +1 -0
- package/dist/utils/reporter-utils.d.ts +42 -0
- package/dist/utils/reporter-utils.d.ts.map +1 -0
- package/dist/utils/reporter-utils.js +83 -0
- package/dist/utils/reporter-utils.js.map +1 -0
- package/package.json +4 -4
- package/src/cli/commands/run.ts +127 -68
- package/src/constants.ts +2 -0
- package/src/errors/index.ts +2 -0
- package/src/errors/reporter.ts +55 -0
- package/src/index.ts +19 -1
- package/src/services/reporter-loader.ts +323 -0
- package/src/types/index.ts +3 -0
- package/src/types/plugin.ts +197 -0
- package/src/utils/package.ts +32 -1
- package/src/utils/reporter-utils.ts +85 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ModestBench Reporter Utilities
|
|
4
|
+
*
|
|
5
|
+
* Formatting functions for benchmark data, exported for use by third-party
|
|
6
|
+
* reporter plugins.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.reporterUtils = exports.formatPercentage = exports.formatOpsPerSecond = exports.formatDuration = exports.formatBytes = void 0;
|
|
10
|
+
/**
|
|
11
|
+
* Format bytes in human-readable format
|
|
12
|
+
*
|
|
13
|
+
* @param bytes - Number of bytes
|
|
14
|
+
* @returns Formatted string (e.g., "1.5 GB", "256 MB", "1.2 KB")
|
|
15
|
+
*/
|
|
16
|
+
const formatBytes = (bytes) => {
|
|
17
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
18
|
+
let size = bytes;
|
|
19
|
+
let unitIndex = 0;
|
|
20
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
21
|
+
size /= 1024;
|
|
22
|
+
unitIndex++;
|
|
23
|
+
}
|
|
24
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
25
|
+
};
|
|
26
|
+
exports.formatBytes = formatBytes;
|
|
27
|
+
/**
|
|
28
|
+
* Format duration in human-readable format
|
|
29
|
+
*
|
|
30
|
+
* @param nanoseconds - Duration in nanoseconds
|
|
31
|
+
* @returns Formatted string (e.g., "1.23ms", "456.78μs", "789.00ns")
|
|
32
|
+
*/
|
|
33
|
+
const formatDuration = (nanoseconds) => {
|
|
34
|
+
if (nanoseconds < 1000) {
|
|
35
|
+
return `${nanoseconds.toFixed(2)}ns`;
|
|
36
|
+
}
|
|
37
|
+
else if (nanoseconds < 1_000_000) {
|
|
38
|
+
return `${(nanoseconds / 1000).toFixed(2)}μs`;
|
|
39
|
+
}
|
|
40
|
+
else if (nanoseconds < 1_000_000_000) {
|
|
41
|
+
return `${(nanoseconds / 1_000_000).toFixed(2)}ms`;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return `${(nanoseconds / 1_000_000_000).toFixed(2)}s`;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.formatDuration = formatDuration;
|
|
48
|
+
/**
|
|
49
|
+
* Format operations per second in human-readable format
|
|
50
|
+
*
|
|
51
|
+
* @param opsPerSecond - Operations per second
|
|
52
|
+
* @returns Formatted string (e.g., "1.2M ops/sec", "456K ops/sec")
|
|
53
|
+
*/
|
|
54
|
+
const formatOpsPerSecond = (opsPerSecond) => {
|
|
55
|
+
if (opsPerSecond < 1000) {
|
|
56
|
+
return `${opsPerSecond.toFixed(2)} ops/sec`;
|
|
57
|
+
}
|
|
58
|
+
else if (opsPerSecond < 1_000_000) {
|
|
59
|
+
return `${(opsPerSecond / 1000).toFixed(2)}K ops/sec`;
|
|
60
|
+
}
|
|
61
|
+
else if (opsPerSecond < 1_000_000_000) {
|
|
62
|
+
return `${(opsPerSecond / 1_000_000).toFixed(2)}M ops/sec`;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return `${(opsPerSecond / 1_000_000_000).toFixed(2)}B ops/sec`;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
exports.formatOpsPerSecond = formatOpsPerSecond;
|
|
69
|
+
/**
|
|
70
|
+
* Format percentage value
|
|
71
|
+
*
|
|
72
|
+
* @param value - Percentage value (e.g., 12.345 for 12.345%)
|
|
73
|
+
* @returns Formatted string (e.g., "12.35%")
|
|
74
|
+
*/
|
|
75
|
+
const formatPercentage = (value) => {
|
|
76
|
+
return `${value.toFixed(2)}%`;
|
|
77
|
+
};
|
|
78
|
+
exports.formatPercentage = formatPercentage;
|
|
79
|
+
/**
|
|
80
|
+
* Reporter utilities object implementing the ReporterUtils interface
|
|
81
|
+
*
|
|
82
|
+
* This object is provided to reporter plugins via the ReporterContext.
|
|
83
|
+
*/
|
|
84
|
+
exports.reporterUtils = {
|
|
85
|
+
formatBytes: exports.formatBytes,
|
|
86
|
+
formatDuration: exports.formatDuration,
|
|
87
|
+
formatOpsPerSecond: exports.formatOpsPerSecond,
|
|
88
|
+
formatPercentage: exports.formatPercentage,
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=reporter-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter-utils.js","sourceRoot":"","sources":["../../src/utils/reporter-utils.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAIH;;;;;GAKG;AACI,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE;IACnD,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,IAAI,CAAC;QACb,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AAClD,CAAC,CAAC;AAXW,QAAA,WAAW,eAWtB;AAEF;;;;;GAKG;AACI,MAAM,cAAc,GAAG,CAAC,WAAmB,EAAU,EAAE;IAC5D,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;SAAM,IAAI,WAAW,GAAG,SAAS,EAAE,CAAC;QACnC,OAAO,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;SAAM,IAAI,WAAW,GAAG,aAAa,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAC,WAAW,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,CAAC;AACH,CAAC,CAAC;AAVW,QAAA,cAAc,kBAUzB;AAEF;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,CAAC,YAAoB,EAAU,EAAE;IACjE,IAAI,YAAY,GAAG,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC9C,CAAC;SAAM,IAAI,YAAY,GAAG,SAAS,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IACxD,CAAC;SAAM,IAAI,YAAY,GAAG,aAAa,EAAE,CAAC;QACxC,OAAO,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IACjE,CAAC;AACH,CAAC,CAAC;AAVW,QAAA,kBAAkB,sBAU7B;AAEF;;;;;GAKG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAU,EAAE;IACxD,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAChC,CAAC,CAAC;AAFW,QAAA,gBAAgB,oBAE3B;AAEF;;;;GAIG;AACU,QAAA,aAAa,GAAkB;IAC1C,WAAW,EAAX,mBAAW;IACX,cAAc,EAAd,sBAAc;IACd,kBAAkB,EAAlB,0BAAkB;IAClB,gBAAgB,EAAhB,wBAAgB;CACjB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ModestBench Reporter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Formatting functions for benchmark data, exported for use by third-party
|
|
5
|
+
* reporter plugins.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReporterUtils } from "../types/plugin.cjs";
|
|
8
|
+
/**
|
|
9
|
+
* Format bytes in human-readable format
|
|
10
|
+
*
|
|
11
|
+
* @param bytes - Number of bytes
|
|
12
|
+
* @returns Formatted string (e.g., "1.5 GB", "256 MB", "1.2 KB")
|
|
13
|
+
*/
|
|
14
|
+
export declare const formatBytes: (bytes: number) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Format duration in human-readable format
|
|
17
|
+
*
|
|
18
|
+
* @param nanoseconds - Duration in nanoseconds
|
|
19
|
+
* @returns Formatted string (e.g., "1.23ms", "456.78μs", "789.00ns")
|
|
20
|
+
*/
|
|
21
|
+
export declare const formatDuration: (nanoseconds: number) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Format operations per second in human-readable format
|
|
24
|
+
*
|
|
25
|
+
* @param opsPerSecond - Operations per second
|
|
26
|
+
* @returns Formatted string (e.g., "1.2M ops/sec", "456K ops/sec")
|
|
27
|
+
*/
|
|
28
|
+
export declare const formatOpsPerSecond: (opsPerSecond: number) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Format percentage value
|
|
31
|
+
*
|
|
32
|
+
* @param value - Percentage value (e.g., 12.345 for 12.345%)
|
|
33
|
+
* @returns Formatted string (e.g., "12.35%")
|
|
34
|
+
*/
|
|
35
|
+
export declare const formatPercentage: (value: number) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Reporter utilities object implementing the ReporterUtils interface
|
|
38
|
+
*
|
|
39
|
+
* This object is provided to reporter plugins via the ReporterContext.
|
|
40
|
+
*/
|
|
41
|
+
export declare const reporterUtils: ReporterUtils;
|
|
42
|
+
//# sourceMappingURL=reporter-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter-utils.d.ts","sourceRoot":"","sources":["../../src/utils/reporter-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,4BAA2B;AAExD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAW3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,aAAa,MAAM,KAAG,MAUpD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,cAAc,MAAM,KAAG,MAUzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAEhD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ModestBench Reporter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Formatting functions for benchmark data, exported for use by third-party
|
|
5
|
+
* reporter plugins.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReporterUtils } from "../types/plugin.js";
|
|
8
|
+
/**
|
|
9
|
+
* Format bytes in human-readable format
|
|
10
|
+
*
|
|
11
|
+
* @param bytes - Number of bytes
|
|
12
|
+
* @returns Formatted string (e.g., "1.5 GB", "256 MB", "1.2 KB")
|
|
13
|
+
*/
|
|
14
|
+
export declare const formatBytes: (bytes: number) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Format duration in human-readable format
|
|
17
|
+
*
|
|
18
|
+
* @param nanoseconds - Duration in nanoseconds
|
|
19
|
+
* @returns Formatted string (e.g., "1.23ms", "456.78μs", "789.00ns")
|
|
20
|
+
*/
|
|
21
|
+
export declare const formatDuration: (nanoseconds: number) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Format operations per second in human-readable format
|
|
24
|
+
*
|
|
25
|
+
* @param opsPerSecond - Operations per second
|
|
26
|
+
* @returns Formatted string (e.g., "1.2M ops/sec", "456K ops/sec")
|
|
27
|
+
*/
|
|
28
|
+
export declare const formatOpsPerSecond: (opsPerSecond: number) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Format percentage value
|
|
31
|
+
*
|
|
32
|
+
* @param value - Percentage value (e.g., 12.345 for 12.345%)
|
|
33
|
+
* @returns Formatted string (e.g., "12.35%")
|
|
34
|
+
*/
|
|
35
|
+
export declare const formatPercentage: (value: number) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Reporter utilities object implementing the ReporterUtils interface
|
|
38
|
+
*
|
|
39
|
+
* This object is provided to reporter plugins via the ReporterContext.
|
|
40
|
+
*/
|
|
41
|
+
export declare const reporterUtils: ReporterUtils;
|
|
42
|
+
//# sourceMappingURL=reporter-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter-utils.d.ts","sourceRoot":"","sources":["../../src/utils/reporter-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,2BAA2B;AAExD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAW3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,aAAa,MAAM,KAAG,MAUpD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,cAAc,MAAM,KAAG,MAUzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAEhD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ModestBench Reporter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Formatting functions for benchmark data, exported for use by third-party
|
|
5
|
+
* reporter plugins.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Format bytes in human-readable format
|
|
9
|
+
*
|
|
10
|
+
* @param bytes - Number of bytes
|
|
11
|
+
* @returns Formatted string (e.g., "1.5 GB", "256 MB", "1.2 KB")
|
|
12
|
+
*/
|
|
13
|
+
export const formatBytes = (bytes) => {
|
|
14
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
15
|
+
let size = bytes;
|
|
16
|
+
let unitIndex = 0;
|
|
17
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
18
|
+
size /= 1024;
|
|
19
|
+
unitIndex++;
|
|
20
|
+
}
|
|
21
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Format duration in human-readable format
|
|
25
|
+
*
|
|
26
|
+
* @param nanoseconds - Duration in nanoseconds
|
|
27
|
+
* @returns Formatted string (e.g., "1.23ms", "456.78μs", "789.00ns")
|
|
28
|
+
*/
|
|
29
|
+
export const formatDuration = (nanoseconds) => {
|
|
30
|
+
if (nanoseconds < 1000) {
|
|
31
|
+
return `${nanoseconds.toFixed(2)}ns`;
|
|
32
|
+
}
|
|
33
|
+
else if (nanoseconds < 1_000_000) {
|
|
34
|
+
return `${(nanoseconds / 1000).toFixed(2)}μs`;
|
|
35
|
+
}
|
|
36
|
+
else if (nanoseconds < 1_000_000_000) {
|
|
37
|
+
return `${(nanoseconds / 1_000_000).toFixed(2)}ms`;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return `${(nanoseconds / 1_000_000_000).toFixed(2)}s`;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Format operations per second in human-readable format
|
|
45
|
+
*
|
|
46
|
+
* @param opsPerSecond - Operations per second
|
|
47
|
+
* @returns Formatted string (e.g., "1.2M ops/sec", "456K ops/sec")
|
|
48
|
+
*/
|
|
49
|
+
export const formatOpsPerSecond = (opsPerSecond) => {
|
|
50
|
+
if (opsPerSecond < 1000) {
|
|
51
|
+
return `${opsPerSecond.toFixed(2)} ops/sec`;
|
|
52
|
+
}
|
|
53
|
+
else if (opsPerSecond < 1_000_000) {
|
|
54
|
+
return `${(opsPerSecond / 1000).toFixed(2)}K ops/sec`;
|
|
55
|
+
}
|
|
56
|
+
else if (opsPerSecond < 1_000_000_000) {
|
|
57
|
+
return `${(opsPerSecond / 1_000_000).toFixed(2)}M ops/sec`;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return `${(opsPerSecond / 1_000_000_000).toFixed(2)}B ops/sec`;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Format percentage value
|
|
65
|
+
*
|
|
66
|
+
* @param value - Percentage value (e.g., 12.345 for 12.345%)
|
|
67
|
+
* @returns Formatted string (e.g., "12.35%")
|
|
68
|
+
*/
|
|
69
|
+
export const formatPercentage = (value) => {
|
|
70
|
+
return `${value.toFixed(2)}%`;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Reporter utilities object implementing the ReporterUtils interface
|
|
74
|
+
*
|
|
75
|
+
* This object is provided to reporter plugins via the ReporterContext.
|
|
76
|
+
*/
|
|
77
|
+
export const reporterUtils = {
|
|
78
|
+
formatBytes,
|
|
79
|
+
formatDuration,
|
|
80
|
+
formatOpsPerSecond,
|
|
81
|
+
formatPercentage,
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=reporter-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter-utils.js","sourceRoot":"","sources":["../../src/utils/reporter-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE;IACnD,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,IAAI,CAAC;QACb,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAmB,EAAU,EAAE;IAC5D,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;SAAM,IAAI,WAAW,GAAG,SAAS,EAAE,CAAC;QACnC,OAAO,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;SAAM,IAAI,WAAW,GAAG,aAAa,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAC,WAAW,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,CAAC;AACH,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,YAAoB,EAAU,EAAE;IACjE,IAAI,YAAY,GAAG,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC9C,CAAC;SAAM,IAAI,YAAY,GAAG,SAAS,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IACxD,CAAC;SAAM,IAAI,YAAY,GAAG,aAAa,EAAE,CAAC;QACxC,OAAO,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IACjE,CAAC;AACH,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAU,EAAE;IACxD,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAChC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,WAAW;IACX,cAAc;IACd,kBAAkB;IAClB,gBAAgB;CACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modestbench",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A full-ass benchmarking framework for Node.js",
|
|
6
6
|
"repository": {
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"clean": "rm -rf dist",
|
|
95
95
|
"commitlint": "commitlint",
|
|
96
96
|
"dev": "zshy --watch",
|
|
97
|
-
"docs:build": "run-s docs:copy astro:build",
|
|
97
|
+
"docs:build": "run-s build:schema docs:copy astro:build",
|
|
98
98
|
"docs:copy": "tsx scripts/copy-docs.ts",
|
|
99
99
|
"docs:dev": "run-s docs:copy astro:dev",
|
|
100
100
|
"docs:preview": "astro preview --config astro.config.js",
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
"@types/node": "24.10.3",
|
|
145
145
|
"@types/wallabyjs": "0.0.15",
|
|
146
146
|
"@types/yargs": "17.0.35",
|
|
147
|
-
"asciinema-player": "3.
|
|
147
|
+
"asciinema-player": "3.13.2",
|
|
148
148
|
"astro": "5.16.5",
|
|
149
149
|
"astro-broken-link-checker": "file:./vendor/astro-broken-link-checker",
|
|
150
150
|
"ava": "6.4.1",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"globals": "16.5.0",
|
|
157
157
|
"husky": "9.1.7",
|
|
158
158
|
"jest": "30.2.0",
|
|
159
|
-
"knip": "5.73.
|
|
159
|
+
"knip": "5.73.4",
|
|
160
160
|
"lint-staged": "16.2.7",
|
|
161
161
|
"markdownlint-cli2": "0.20.0",
|
|
162
162
|
"markdownlint-cli2-formatter-pretty": "0.0.9",
|
package/src/cli/commands/run.ts
CHANGED
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
import { resolve } from 'node:path';
|
|
9
9
|
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
BenchmarkRun,
|
|
12
|
+
ModestBenchConfig,
|
|
13
|
+
Reporter,
|
|
14
|
+
} from '../../types/index.js';
|
|
11
15
|
import type { CliContext } from '../index.js';
|
|
12
16
|
|
|
13
17
|
import { ErrorCodes, ExitCodes } from '../../constants.js';
|
|
@@ -15,6 +19,8 @@ import { resolveOutputPath } from '../../core/output-path-resolver.js';
|
|
|
15
19
|
import {
|
|
16
20
|
type BudgetExceededError,
|
|
17
21
|
InvalidArgumentError,
|
|
22
|
+
ReporterLoadError,
|
|
23
|
+
ReporterValidationError,
|
|
18
24
|
UnknownReporterError,
|
|
19
25
|
} from '../../errors/index.js';
|
|
20
26
|
import { CsvReporter } from '../../reporters/csv.js';
|
|
@@ -22,6 +28,11 @@ import { HumanReporter } from '../../reporters/human.js';
|
|
|
22
28
|
import { JsonReporter } from '../../reporters/json.js';
|
|
23
29
|
import { NyanReporter } from '../../reporters/nyan.js';
|
|
24
30
|
import { SimpleReporter } from '../../reporters/simple.js';
|
|
31
|
+
import {
|
|
32
|
+
isBuiltInReporter,
|
|
33
|
+
isFilePath,
|
|
34
|
+
loadReporter,
|
|
35
|
+
} from '../../services/reporter-loader.js';
|
|
25
36
|
import { hasErrorCode, isError } from '../../utils/type-guards.js';
|
|
26
37
|
|
|
27
38
|
/**
|
|
@@ -106,7 +117,7 @@ export const handleRunCommand = async (
|
|
|
106
117
|
if (showCliMessages) {
|
|
107
118
|
console.error('Setting up reporters...');
|
|
108
119
|
}
|
|
109
|
-
const reporters = setupReporters(
|
|
120
|
+
const reporters = await setupReporters(
|
|
110
121
|
context,
|
|
111
122
|
config,
|
|
112
123
|
verbose,
|
|
@@ -370,19 +381,26 @@ const loadConfiguration = async (context: CliContext, options: RunOptions) => {
|
|
|
370
381
|
|
|
371
382
|
/**
|
|
372
383
|
* Setup and configure reporters based on configuration
|
|
384
|
+
*
|
|
385
|
+
* Supports built-in reporters, registry-based custom reporters, and external
|
|
386
|
+
* reporters loaded from file paths or npm packages.
|
|
373
387
|
*/
|
|
374
|
-
const setupReporters = (
|
|
388
|
+
const setupReporters = async (
|
|
375
389
|
context: CliContext,
|
|
376
|
-
config: {
|
|
390
|
+
config: {
|
|
391
|
+
outputDir?: string;
|
|
392
|
+
reporterConfig?: Record<string, unknown>;
|
|
393
|
+
reporters?: string[];
|
|
394
|
+
},
|
|
377
395
|
isVerbose: boolean,
|
|
378
396
|
showCliMessages: boolean,
|
|
379
397
|
explicitQuiet: boolean,
|
|
380
398
|
explicitOutputDir?: string,
|
|
381
399
|
explicitOutputFile?: string,
|
|
382
400
|
progressOption?: boolean,
|
|
383
|
-
) => {
|
|
401
|
+
): Promise<Reporter[]> => {
|
|
384
402
|
try {
|
|
385
|
-
const reporters = [];
|
|
403
|
+
const reporters: Reporter[] = [];
|
|
386
404
|
// Dedupe requested reporters
|
|
387
405
|
const requestedReporters = [...new Set(config.reporters || ['human'])];
|
|
388
406
|
|
|
@@ -398,67 +416,103 @@ const setupReporters = (
|
|
|
398
416
|
const builtInReporters = ['human', 'json', 'csv', 'nyan', 'simple'];
|
|
399
417
|
|
|
400
418
|
for (const reporterName of requestedReporters) {
|
|
401
|
-
let reporter;
|
|
402
|
-
|
|
403
|
-
//
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
419
|
+
let reporter: Reporter;
|
|
420
|
+
|
|
421
|
+
// Check if this is a built-in reporter
|
|
422
|
+
if (isBuiltInReporter(reporterName)) {
|
|
423
|
+
// Create reporter instances with output path configuration
|
|
424
|
+
switch (reporterName) {
|
|
425
|
+
case 'csv': {
|
|
426
|
+
const outputPath = resolveOutputPath(
|
|
427
|
+
outputDir,
|
|
428
|
+
explicitOutputFile,
|
|
429
|
+
'results.csv',
|
|
430
|
+
);
|
|
431
|
+
reporter = new CsvReporter({
|
|
432
|
+
includeHeaders: true,
|
|
433
|
+
includeMetadata: true,
|
|
434
|
+
...(outputPath ? { outputPath } : {}),
|
|
435
|
+
quiet: explicitQuiet,
|
|
436
|
+
verbose: isVerbose,
|
|
437
|
+
});
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
420
440
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
441
|
+
case 'human':
|
|
442
|
+
reporter = new HumanReporter({
|
|
443
|
+
color: true,
|
|
444
|
+
progress: progressOption ?? true,
|
|
445
|
+
quiet: explicitQuiet,
|
|
446
|
+
verbose: isVerbose,
|
|
447
|
+
});
|
|
448
|
+
break;
|
|
449
|
+
|
|
450
|
+
case 'json': {
|
|
451
|
+
const outputPath = resolveOutputPath(
|
|
452
|
+
outputDir,
|
|
453
|
+
explicitOutputFile,
|
|
454
|
+
'results.json',
|
|
455
|
+
);
|
|
456
|
+
reporter = new JsonReporter({
|
|
457
|
+
...(outputPath ? { outputPath } : {}),
|
|
458
|
+
prettyPrint: true,
|
|
459
|
+
});
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
442
462
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
463
|
+
case 'nyan':
|
|
464
|
+
reporter = new NyanReporter({
|
|
465
|
+
color: true,
|
|
466
|
+
quiet: explicitQuiet,
|
|
467
|
+
});
|
|
468
|
+
break;
|
|
469
|
+
|
|
470
|
+
case 'simple':
|
|
471
|
+
reporter = new SimpleReporter({
|
|
472
|
+
quiet: explicitQuiet,
|
|
473
|
+
verbose: isVerbose,
|
|
474
|
+
});
|
|
475
|
+
break;
|
|
476
|
+
|
|
477
|
+
default:
|
|
478
|
+
// TypeScript exhaustiveness check - should never reach here
|
|
479
|
+
throw new Error(`Unhandled built-in reporter: ${reporterName}`);
|
|
480
|
+
}
|
|
481
|
+
} else if (isFilePath(reporterName)) {
|
|
482
|
+
// External reporter from file path
|
|
483
|
+
const reporterOptions =
|
|
484
|
+
(config.reporterConfig?.[reporterName] as Record<string, unknown>) ??
|
|
485
|
+
{};
|
|
486
|
+
if (showCliMessages) {
|
|
487
|
+
console.error(`Loading external reporter: ${reporterName}`);
|
|
488
|
+
}
|
|
489
|
+
reporter = await loadReporter(reporterName, reporterOptions);
|
|
490
|
+
} else {
|
|
491
|
+
// Try registry first, then npm package
|
|
492
|
+
const registryReporter = context.reporterRegistry.get(reporterName);
|
|
493
|
+
if (registryReporter) {
|
|
494
|
+
reporter = registryReporter;
|
|
495
|
+
} else {
|
|
496
|
+
// Try loading as npm package
|
|
497
|
+
const reporterOptions =
|
|
498
|
+
(config.reporterConfig?.[reporterName] as Record<
|
|
499
|
+
string,
|
|
500
|
+
unknown
|
|
501
|
+
>) ?? {};
|
|
502
|
+
if (showCliMessages) {
|
|
503
|
+
console.error(`Loading reporter package: ${reporterName}`);
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
reporter = await loadReporter(reporterName, reporterOptions);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
// If loading fails and it's not a file path, provide helpful error
|
|
509
|
+
if (
|
|
510
|
+
error instanceof ReporterLoadError ||
|
|
511
|
+
error instanceof ReporterValidationError
|
|
512
|
+
) {
|
|
513
|
+
throw error;
|
|
514
|
+
}
|
|
515
|
+
// Combine built-in reporters with registered custom reporters for error message
|
|
462
516
|
const registeredReporters = Object.keys(
|
|
463
517
|
context.reporterRegistry.getAll(),
|
|
464
518
|
);
|
|
@@ -467,10 +521,11 @@ const setupReporters = (
|
|
|
467
521
|
...registeredReporters,
|
|
468
522
|
];
|
|
469
523
|
throw new UnknownReporterError(
|
|
470
|
-
`Unknown reporter: ${reporterName}. Available: ${availableReporters.join(', ')}
|
|
524
|
+
`Unknown reporter: ${reporterName}. Available built-in reporters: ${availableReporters.join(', ')}. ` +
|
|
525
|
+
`For external reporters, use a file path (./my-reporter.js) or npm package name.`,
|
|
471
526
|
);
|
|
472
527
|
}
|
|
473
|
-
|
|
528
|
+
}
|
|
474
529
|
}
|
|
475
530
|
|
|
476
531
|
reporters.push(reporter);
|
|
@@ -484,7 +539,11 @@ const setupReporters = (
|
|
|
484
539
|
} catch (error) {
|
|
485
540
|
// Re-throw our custom errors
|
|
486
541
|
const errorCode = hasErrorCode(error) ? error.code : undefined;
|
|
487
|
-
if (
|
|
542
|
+
if (
|
|
543
|
+
errorCode === ErrorCodes.REPORTER_UNKNOWN ||
|
|
544
|
+
errorCode === ErrorCodes.REPORTER_LOAD_FAILED ||
|
|
545
|
+
errorCode === ErrorCodes.REPORTER_INVALID
|
|
546
|
+
) {
|
|
488
547
|
throw error;
|
|
489
548
|
}
|
|
490
549
|
throw new InvalidArgumentError(
|
package/src/constants.ts
CHANGED
|
@@ -110,6 +110,8 @@ export const ErrorCodes = {
|
|
|
110
110
|
|
|
111
111
|
//#region reporter-errors
|
|
112
112
|
REPORTER_ALREADY_REGISTERED: 'ERR_MB_REPORTER_ALREADY_REGISTERED',
|
|
113
|
+
REPORTER_INVALID: 'ERR_MB_REPORTER_INVALID',
|
|
114
|
+
REPORTER_LOAD_FAILED: 'ERR_MB_REPORTER_LOAD_FAILED',
|
|
113
115
|
REPORTER_OUTPUT_FAILED: 'ERR_MB_REPORTER_OUTPUT_FAILED',
|
|
114
116
|
REPORTER_UNKNOWN: 'ERR_MB_REPORTER_UNKNOWN',
|
|
115
117
|
//#endregion
|
package/src/errors/index.ts
CHANGED
package/src/errors/reporter.ts
CHANGED
|
@@ -16,6 +16,26 @@ export class ReporterAlreadyRegisteredError extends ModestBenchError {
|
|
|
16
16
|
readonly code = 'ERR_MB_REPORTER_ALREADY_REGISTERED';
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Reporter load failed
|
|
21
|
+
*
|
|
22
|
+
* Thrown when a reporter module cannot be loaded (file not found, syntax error,
|
|
23
|
+
* invalid module format, etc.).
|
|
24
|
+
*/
|
|
25
|
+
export class ReporterLoadError extends ModestBenchError {
|
|
26
|
+
readonly code = 'ERR_MB_REPORTER_LOAD_FAILED';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The specifier (file path or package name) that failed to load
|
|
30
|
+
*/
|
|
31
|
+
readonly specifier: string;
|
|
32
|
+
|
|
33
|
+
constructor(message: string, specifier: string, options?: ErrorOptions) {
|
|
34
|
+
super(`Failed to load reporter "${specifier}": ${message}`, options);
|
|
35
|
+
this.specifier = specifier;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
/**
|
|
20
40
|
* Reporter output failed
|
|
21
41
|
*
|
|
@@ -25,6 +45,41 @@ export class ReporterOutputError extends ModestBenchError {
|
|
|
25
45
|
readonly code = 'ERR_MB_REPORTER_OUTPUT_FAILED';
|
|
26
46
|
}
|
|
27
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Reporter validation failed
|
|
50
|
+
*
|
|
51
|
+
* Thrown when a loaded module does not implement the required Reporter
|
|
52
|
+
* interface methods.
|
|
53
|
+
*/
|
|
54
|
+
export class ReporterValidationError extends ModestBenchError {
|
|
55
|
+
readonly code = 'ERR_MB_REPORTER_INVALID';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The methods that are missing from the reporter
|
|
59
|
+
*/
|
|
60
|
+
readonly missingMethods: string[];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The specifier (file path or package name) of the invalid reporter
|
|
64
|
+
*/
|
|
65
|
+
readonly specifier: string;
|
|
66
|
+
|
|
67
|
+
constructor(
|
|
68
|
+
message: string,
|
|
69
|
+
specifier: string,
|
|
70
|
+
missingMethods: string[] = [],
|
|
71
|
+
options?: ErrorOptions,
|
|
72
|
+
) {
|
|
73
|
+
const methodsInfo =
|
|
74
|
+
missingMethods.length > 0
|
|
75
|
+
? ` Missing required methods: ${missingMethods.join(', ')}.`
|
|
76
|
+
: '';
|
|
77
|
+
super(`Invalid reporter "${specifier}": ${message}${methodsInfo}`, options);
|
|
78
|
+
this.specifier = specifier;
|
|
79
|
+
this.missingMethods = missingMethods;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
28
83
|
/**
|
|
29
84
|
* Unknown reporter
|
|
30
85
|
*
|