modestbench 0.6.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 +19 -0
- package/README.md +6 -2
- package/dist/cli/commands/run.cjs +100 -54
- 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 +93 -47
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/test.cjs +14 -15
- package/dist/cli/commands/test.cjs.map +1 -1
- package/dist/cli/commands/test.d.cts.map +1 -1
- package/dist/cli/commands/test.d.ts.map +1 -1
- package/dist/cli/commands/test.js +2 -3
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/index.cjs +3 -0
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/constants.cjs +3 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +3 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -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 +19 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/reporters/index.cjs +3 -1
- package/dist/reporters/index.cjs.map +1 -1
- package/dist/reporters/index.d.cts +1 -0
- package/dist/reporters/index.d.cts.map +1 -1
- package/dist/reporters/index.d.ts +1 -0
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js +1 -0
- package/dist/reporters/index.js.map +1 -1
- package/dist/reporters/nyan.cjs +318 -0
- package/dist/reporters/nyan.cjs.map +1 -0
- package/dist/reporters/nyan.d.cts +118 -0
- package/dist/reporters/nyan.d.cts.map +1 -0
- package/dist/reporters/nyan.d.ts +118 -0
- package/dist/reporters/nyan.d.ts.map +1 -0
- package/dist/reporters/nyan.js +314 -0
- package/dist/reporters/nyan.js.map +1 -0
- 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/core.cjs.map +1 -1
- package/dist/types/core.d.cts +13 -12
- package/dist/types/core.d.cts.map +1 -1
- package/dist/types/core.d.ts +13 -12
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js.map +1 -1
- package/dist/types/index.cjs +0 -2
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -2
- 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 +6 -6
- package/src/cli/commands/run.ts +130 -64
- package/src/cli/commands/test.ts +2 -3
- package/src/cli/index.ts +8 -0
- package/src/constants.ts +4 -1
- package/src/errors/index.ts +2 -0
- package/src/errors/reporter.ts +55 -0
- package/src/index.ts +22 -1
- package/src/reporters/index.ts +1 -0
- package/src/reporters/nyan.ts +409 -0
- package/src/services/reporter-loader.ts +323 -0
- package/src/types/core.ts +16 -14
- package/src/types/index.ts +3 -3
- package/src/types/plugin.ts +197 -0
- package/src/utils/package.ts +32 -1
- package/src/utils/reporter-utils.ts +85 -0
- package/dist/types/cli.cjs +0 -12
- package/dist/types/cli.cjs.map +0 -1
- package/dist/types/cli.d.cts +0 -75
- package/dist/types/cli.d.cts.map +0 -1
- package/dist/types/cli.d.ts +0 -75
- package/dist/types/cli.d.ts.map +0 -1
- package/dist/types/cli.js +0 -9
- package/dist/types/cli.js.map +0 -1
- package/src/types/cli.ts +0 -82
|
@@ -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",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"zod": "4.1.13"
|
|
133
133
|
},
|
|
134
134
|
"devDependencies": {
|
|
135
|
-
"@astrojs/mdx": "4.3.
|
|
135
|
+
"@astrojs/mdx": "4.3.13",
|
|
136
136
|
"@astrojs/starlight": "0.37.1",
|
|
137
137
|
"@commitlint/cli": "20.2.0",
|
|
138
138
|
"@commitlint/config-conventional": "20.2.0",
|
|
@@ -144,8 +144,8 @@
|
|
|
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.
|
|
148
|
-
"astro": "5.16.
|
|
147
|
+
"asciinema-player": "3.13.2",
|
|
148
|
+
"astro": "5.16.5",
|
|
149
149
|
"astro-broken-link-checker": "file:./vendor/astro-broken-link-checker",
|
|
150
150
|
"ava": "6.4.1",
|
|
151
151
|
"bupkis": "0.14.0",
|
|
@@ -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,21 +7,32 @@
|
|
|
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
|
-
import { ErrorCodes } from '../../constants.js';
|
|
17
|
+
import { ErrorCodes, ExitCodes } from '../../constants.js';
|
|
14
18
|
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';
|
|
21
27
|
import { HumanReporter } from '../../reporters/human.js';
|
|
22
28
|
import { JsonReporter } from '../../reporters/json.js';
|
|
29
|
+
import { NyanReporter } from '../../reporters/nyan.js';
|
|
23
30
|
import { SimpleReporter } from '../../reporters/simple.js';
|
|
24
|
-
import {
|
|
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
|
|
|
@@ -395,63 +413,106 @@ const setupReporters = (
|
|
|
395
413
|
: undefined;
|
|
396
414
|
|
|
397
415
|
// Built-in reporter names for error messages
|
|
398
|
-
const builtInReporters = ['human', 'json', 'csv', 'simple'];
|
|
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
|
-
|
|
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
|
|
455
516
|
const registeredReporters = Object.keys(
|
|
456
517
|
context.reporterRegistry.getAll(),
|
|
457
518
|
);
|
|
@@ -460,10 +521,11 @@ const setupReporters = (
|
|
|
460
521
|
...registeredReporters,
|
|
461
522
|
];
|
|
462
523
|
throw new UnknownReporterError(
|
|
463
|
-
`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.`,
|
|
464
526
|
);
|
|
465
527
|
}
|
|
466
|
-
|
|
528
|
+
}
|
|
467
529
|
}
|
|
468
530
|
|
|
469
531
|
reporters.push(reporter);
|
|
@@ -477,7 +539,11 @@ const setupReporters = (
|
|
|
477
539
|
} catch (error) {
|
|
478
540
|
// Re-throw our custom errors
|
|
479
541
|
const errorCode = hasErrorCode(error) ? error.code : undefined;
|
|
480
|
-
if (
|
|
542
|
+
if (
|
|
543
|
+
errorCode === ErrorCodes.REPORTER_UNKNOWN ||
|
|
544
|
+
errorCode === ErrorCodes.REPORTER_LOAD_FAILED ||
|
|
545
|
+
errorCode === ErrorCodes.REPORTER_INVALID
|
|
546
|
+
) {
|
|
481
547
|
throw error;
|
|
482
548
|
}
|
|
483
549
|
throw new InvalidArgumentError(
|
package/src/cli/commands/test.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* executing them through a lightweight benchmark runner.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { hostname } from 'node:os';
|
|
9
|
-
import { cpus, freemem, totalmem } from 'node:os';
|
|
8
|
+
import { cpus, freemem, hostname, totalmem } from 'node:os';
|
|
10
9
|
import { resolve } from 'node:path';
|
|
11
10
|
import { performance } from 'node:perf_hooks';
|
|
12
11
|
|
|
@@ -31,7 +30,7 @@ import {
|
|
|
31
30
|
type ConvertedBenchmarkSuite,
|
|
32
31
|
type TestFramework,
|
|
33
32
|
} from '../../adapters/types.js';
|
|
34
|
-
import { ExitCodes } from '../../
|
|
33
|
+
import { ExitCodes } from '../../constants.js';
|
|
35
34
|
import { createRunId } from '../../types/core.js';
|
|
36
35
|
import { isError } from '../../utils/type-guards.js';
|
|
37
36
|
|
package/src/cli/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
CsvReporter,
|
|
40
40
|
HumanReporter,
|
|
41
41
|
JsonReporter,
|
|
42
|
+
NyanReporter,
|
|
42
43
|
SimpleReporter,
|
|
43
44
|
} from '../reporters/index.js';
|
|
44
45
|
// Import commands
|
|
@@ -1151,6 +1152,13 @@ const createCliContext = async (
|
|
|
1151
1152
|
}),
|
|
1152
1153
|
);
|
|
1153
1154
|
|
|
1155
|
+
engine.registerReporter(
|
|
1156
|
+
'nyan',
|
|
1157
|
+
new NyanReporter({
|
|
1158
|
+
color: !options.noColor,
|
|
1159
|
+
}),
|
|
1160
|
+
);
|
|
1161
|
+
|
|
1154
1162
|
return {
|
|
1155
1163
|
abortController,
|
|
1156
1164
|
configManager: engine.configManager,
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Engine } from './types/
|
|
1
|
+
import { type Engine } from './types/core.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Supported benchmark file extensions
|
|
@@ -60,6 +60,7 @@ export const Reporters = {
|
|
|
60
60
|
CSV: 'csv',
|
|
61
61
|
HUMAN: 'human',
|
|
62
62
|
JSON: 'json',
|
|
63
|
+
NYAN: 'nyan',
|
|
63
64
|
SIMPLE: 'simple',
|
|
64
65
|
} as const;
|
|
65
66
|
|
|
@@ -109,6 +110,8 @@ export const ErrorCodes = {
|
|
|
109
110
|
|
|
110
111
|
//#region reporter-errors
|
|
111
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',
|
|
112
115
|
REPORTER_OUTPUT_FAILED: 'ERR_MB_REPORTER_OUTPUT_FAILED',
|
|
113
116
|
REPORTER_UNKNOWN: 'ERR_MB_REPORTER_UNKNOWN',
|
|
114
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
|
*
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
export { bootstrap as modestbench } from './bootstrap.js';
|
|
10
10
|
|
|
11
|
+
// Constants
|
|
12
|
+
export { ExitCodes } from './constants.js';
|
|
13
|
+
|
|
11
14
|
// Core engine
|
|
12
15
|
export { ModestBenchEngine } from './core/engine.js';
|
|
13
16
|
export { AccurateEngine, TinybenchEngine } from './core/engines/index.js';
|
|
@@ -38,6 +41,15 @@ export { parseProfile } from './services/profiler/profile-parser.js';
|
|
|
38
41
|
|
|
39
42
|
export { runWithProfiling } from './services/profiler/profile-runner.js';
|
|
40
43
|
export { ModestBenchProgressManager } from './services/progress-manager.js';
|
|
44
|
+
// Reporter plugin loader
|
|
45
|
+
export {
|
|
46
|
+
createReporterContext,
|
|
47
|
+
isBuiltInReporter,
|
|
48
|
+
isFilePath,
|
|
49
|
+
loadReporter,
|
|
50
|
+
PLUGIN_API_VERSION,
|
|
51
|
+
} from './services/reporter-loader.js';
|
|
52
|
+
|
|
41
53
|
export {
|
|
42
54
|
BaseReporter,
|
|
43
55
|
CompositeReporter,
|
|
@@ -48,4 +60,13 @@ export {
|
|
|
48
60
|
export * from './types/index.js';
|
|
49
61
|
|
|
50
62
|
// Utilities
|
|
51
|
-
export { findPackageRoot } from './utils/package.js';
|
|
63
|
+
export { findPackageRoot, getPackageVersion } from './utils/package.js';
|
|
64
|
+
|
|
65
|
+
// Reporter utilities (for plugin authors)
|
|
66
|
+
export {
|
|
67
|
+
formatBytes,
|
|
68
|
+
formatDuration,
|
|
69
|
+
formatOpsPerSecond,
|
|
70
|
+
formatPercentage,
|
|
71
|
+
reporterUtils,
|
|
72
|
+
} from './utils/reporter-utils.js';
|