modestbench 0.2.0 → 0.3.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/CHANGELOG.md +27 -0
- package/README.md +131 -34
- package/dist/cli/commands/analyze.cjs +60 -0
- package/dist/cli/commands/analyze.cjs.map +1 -0
- package/dist/cli/commands/analyze.d.cts +35 -0
- package/dist/cli/commands/analyze.d.cts.map +1 -0
- package/dist/cli/commands/analyze.d.ts +35 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +56 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/baseline.cjs +404 -0
- package/dist/cli/commands/baseline.cjs.map +1 -0
- package/dist/cli/commands/baseline.d.cts +72 -0
- package/dist/cli/commands/baseline.d.cts.map +1 -0
- package/dist/cli/commands/baseline.d.ts +72 -0
- package/dist/cli/commands/baseline.d.ts.map +1 -0
- package/dist/cli/commands/baseline.js +396 -0
- package/dist/cli/commands/baseline.js.map +1 -0
- package/dist/cli/commands/history.d.cts +1 -1
- package/dist/cli/commands/history.d.cts.map +1 -1
- package/dist/cli/commands/history.d.ts +1 -1
- package/dist/cli/commands/history.d.ts.map +1 -1
- package/dist/cli/commands/init.cjs +99 -166
- package/dist/cli/commands/init.cjs.map +1 -1
- package/dist/cli/commands/init.d.cts +4 -4
- package/dist/cli/commands/init.d.cts.map +1 -1
- package/dist/cli/commands/init.d.ts +4 -4
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +99 -166
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.cjs +146 -127
- package/dist/cli/commands/run.cjs.map +1 -1
- package/dist/cli/commands/run.d.cts +16 -3
- package/dist/cli/commands/run.d.cts.map +1 -1
- package/dist/cli/commands/run.d.ts +16 -3
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +145 -93
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.cjs +583 -394
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +4 -16
- package/dist/cli/index.d.cts.map +1 -1
- package/dist/cli/index.d.ts +4 -16
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +575 -386
- package/dist/cli/index.js.map +1 -1
- package/dist/config/budget-schema.cjs +172 -0
- package/dist/config/budget-schema.cjs.map +1 -0
- package/dist/config/budget-schema.d.cts +59 -0
- package/dist/config/budget-schema.d.cts.map +1 -0
- package/dist/config/budget-schema.d.ts +59 -0
- package/dist/config/budget-schema.d.ts.map +1 -0
- package/dist/config/budget-schema.js +166 -0
- package/dist/config/budget-schema.js.map +1 -0
- package/dist/config/schema.cjs +182 -2
- package/dist/config/schema.cjs.map +1 -1
- package/dist/config/schema.d.cts +122 -3
- package/dist/config/schema.d.cts.map +1 -1
- package/dist/config/schema.d.ts +122 -3
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +180 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/constants.cjs +45 -2
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +41 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.ts +41 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +44 -1
- package/dist/constants.js.map +1 -1
- package/dist/core/engine.cjs +114 -23
- package/dist/core/engine.cjs.map +1 -1
- package/dist/core/engine.d.cts +7 -7
- package/dist/core/engine.d.cts.map +1 -1
- package/dist/core/engine.d.ts +7 -7
- package/dist/core/engine.d.ts.map +1 -1
- package/dist/core/engine.js +115 -24
- package/dist/core/engine.js.map +1 -1
- package/dist/core/engines/accurate-engine.cjs +171 -36
- package/dist/core/engines/accurate-engine.cjs.map +1 -1
- package/dist/core/engines/accurate-engine.d.cts +5 -0
- package/dist/core/engines/accurate-engine.d.cts.map +1 -1
- package/dist/core/engines/accurate-engine.d.ts +5 -0
- package/dist/core/engines/accurate-engine.d.ts.map +1 -1
- package/dist/core/engines/accurate-engine.js +171 -36
- package/dist/core/engines/accurate-engine.js.map +1 -1
- package/dist/core/engines/tinybench-engine.cjs +3 -2
- package/dist/core/engines/tinybench-engine.cjs.map +1 -1
- package/dist/core/engines/tinybench-engine.d.cts.map +1 -1
- package/dist/core/engines/tinybench-engine.d.ts.map +1 -1
- package/dist/core/engines/tinybench-engine.js +3 -2
- package/dist/core/engines/tinybench-engine.js.map +1 -1
- package/dist/core/output-path-resolver.cjs +8 -1
- package/dist/core/output-path-resolver.cjs.map +1 -1
- package/dist/core/output-path-resolver.d.cts.map +1 -1
- package/dist/core/output-path-resolver.d.ts.map +1 -1
- package/dist/core/output-path-resolver.js +9 -2
- package/dist/core/output-path-resolver.js.map +1 -1
- package/dist/errors/base.cjs +12 -3
- package/dist/errors/base.cjs.map +1 -1
- package/dist/errors/base.d.cts +7 -0
- package/dist/errors/base.d.cts.map +1 -1
- package/dist/errors/base.d.ts +7 -0
- package/dist/errors/base.d.ts.map +1 -1
- package/dist/errors/base.js +10 -2
- package/dist/errors/base.js.map +1 -1
- package/dist/errors/budget.cjs +37 -0
- package/dist/errors/budget.cjs.map +1 -0
- package/dist/errors/budget.d.cts +31 -0
- package/dist/errors/budget.d.cts.map +1 -0
- package/dist/errors/budget.d.ts +31 -0
- package/dist/errors/budget.d.ts.map +1 -0
- package/dist/errors/budget.js +33 -0
- package/dist/errors/budget.js.map +1 -0
- package/dist/errors/index.cjs +4 -1
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +1 -0
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/index.cjs +13 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/reporters/csv.cjs +37 -17
- package/dist/reporters/csv.cjs.map +1 -1
- package/dist/reporters/csv.d.cts +3 -6
- package/dist/reporters/csv.d.cts.map +1 -1
- package/dist/reporters/csv.d.ts +3 -6
- package/dist/reporters/csv.d.ts.map +1 -1
- package/dist/reporters/csv.js +37 -17
- package/dist/reporters/csv.js.map +1 -1
- package/dist/reporters/human.cjs +290 -67
- package/dist/reporters/human.cjs.map +1 -1
- package/dist/reporters/human.d.cts +25 -13
- package/dist/reporters/human.d.cts.map +1 -1
- package/dist/reporters/human.d.ts +25 -13
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +290 -67
- package/dist/reporters/human.js.map +1 -1
- package/dist/reporters/json.cjs +23 -48
- package/dist/reporters/json.cjs.map +1 -1
- package/dist/reporters/json.d.cts +2 -28
- package/dist/reporters/json.d.cts.map +1 -1
- package/dist/reporters/json.d.ts +2 -28
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +25 -50
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/profile-human.cjs +154 -0
- package/dist/reporters/profile-human.cjs.map +1 -0
- package/dist/reporters/profile-human.d.cts +44 -0
- package/dist/reporters/profile-human.d.cts.map +1 -0
- package/dist/reporters/profile-human.d.ts +44 -0
- package/dist/reporters/profile-human.d.ts.map +1 -0
- package/dist/reporters/profile-human.js +147 -0
- package/dist/reporters/profile-human.js.map +1 -0
- package/dist/reporters/simple.cjs +67 -45
- package/dist/reporters/simple.cjs.map +1 -1
- package/dist/reporters/simple.d.cts +14 -14
- package/dist/reporters/simple.d.cts.map +1 -1
- package/dist/reporters/simple.d.ts +14 -14
- package/dist/reporters/simple.d.ts.map +1 -1
- package/dist/reporters/simple.js +67 -45
- package/dist/reporters/simple.js.map +1 -1
- package/dist/schema/modestbench-config.schema.json +153 -0
- package/dist/services/baseline-storage.cjs +151 -0
- package/dist/services/baseline-storage.cjs.map +1 -0
- package/dist/services/baseline-storage.d.cts +55 -0
- package/dist/services/baseline-storage.d.cts.map +1 -0
- package/dist/services/baseline-storage.d.ts +55 -0
- package/dist/services/baseline-storage.d.ts.map +1 -0
- package/dist/services/baseline-storage.js +147 -0
- package/dist/services/baseline-storage.js.map +1 -0
- package/dist/services/budget-evaluator.cjs +146 -0
- package/dist/services/budget-evaluator.cjs.map +1 -0
- package/dist/services/budget-evaluator.d.cts +29 -0
- package/dist/services/budget-evaluator.d.cts.map +1 -0
- package/dist/services/budget-evaluator.d.ts +29 -0
- package/dist/services/budget-evaluator.d.ts.map +1 -0
- package/dist/services/budget-evaluator.js +142 -0
- package/dist/services/budget-evaluator.js.map +1 -0
- package/dist/services/config-manager.cjs +24 -10
- package/dist/services/config-manager.cjs.map +1 -1
- package/dist/services/config-manager.d.cts +6 -1
- package/dist/services/config-manager.d.cts.map +1 -1
- package/dist/services/config-manager.d.ts +6 -1
- package/dist/services/config-manager.d.ts.map +1 -1
- package/dist/services/config-manager.js +24 -10
- package/dist/services/config-manager.js.map +1 -1
- package/dist/services/file-loader.cjs +3 -6
- package/dist/services/file-loader.cjs.map +1 -1
- package/dist/services/file-loader.d.cts.map +1 -1
- package/dist/services/file-loader.d.ts.map +1 -1
- package/dist/services/file-loader.js +3 -6
- package/dist/services/file-loader.js.map +1 -1
- package/dist/services/profiler/profile-filter.cjs +116 -0
- package/dist/services/profiler/profile-filter.cjs.map +1 -0
- package/dist/services/profiler/profile-filter.d.cts +20 -0
- package/dist/services/profiler/profile-filter.d.cts.map +1 -0
- package/dist/services/profiler/profile-filter.d.ts +20 -0
- package/dist/services/profiler/profile-filter.d.ts.map +1 -0
- package/dist/services/profiler/profile-filter.js +112 -0
- package/dist/services/profiler/profile-filter.js.map +1 -0
- package/dist/services/profiler/profile-parser.cjs +139 -0
- package/dist/services/profiler/profile-parser.cjs.map +1 -0
- package/dist/services/profiler/profile-parser.d.cts +18 -0
- package/dist/services/profiler/profile-parser.d.cts.map +1 -0
- package/dist/services/profiler/profile-parser.d.ts +18 -0
- package/dist/services/profiler/profile-parser.d.ts.map +1 -0
- package/dist/services/profiler/profile-parser.js +132 -0
- package/dist/services/profiler/profile-parser.js.map +1 -0
- package/dist/services/profiler/profile-runner.cjs +90 -0
- package/dist/services/profiler/profile-runner.cjs.map +1 -0
- package/dist/services/profiler/profile-runner.d.cts +29 -0
- package/dist/services/profiler/profile-runner.d.cts.map +1 -0
- package/dist/services/profiler/profile-runner.d.ts +29 -0
- package/dist/services/profiler/profile-runner.d.ts.map +1 -0
- package/dist/services/profiler/profile-runner.js +86 -0
- package/dist/services/profiler/profile-runner.js.map +1 -0
- package/dist/services/progress-manager.cjs +10 -2
- package/dist/services/progress-manager.cjs.map +1 -1
- package/dist/services/progress-manager.d.cts +2 -0
- package/dist/services/progress-manager.d.cts.map +1 -1
- package/dist/services/progress-manager.d.ts +2 -0
- package/dist/services/progress-manager.d.ts.map +1 -1
- package/dist/services/progress-manager.js +10 -2
- package/dist/services/progress-manager.js.map +1 -1
- package/dist/services/reporter-registry.cjs +18 -24
- package/dist/services/reporter-registry.cjs.map +1 -1
- package/dist/services/reporter-registry.d.cts +18 -40
- package/dist/services/reporter-registry.d.cts.map +1 -1
- package/dist/services/reporter-registry.d.ts +18 -40
- package/dist/services/reporter-registry.d.ts.map +1 -1
- package/dist/services/reporter-registry.js +18 -24
- package/dist/services/reporter-registry.js.map +1 -1
- package/dist/types/budgets.cjs +8 -0
- package/dist/types/budgets.cjs.map +1 -0
- package/dist/types/budgets.d.cts +149 -0
- package/dist/types/budgets.d.cts.map +1 -0
- package/dist/types/budgets.d.ts +149 -0
- package/dist/types/budgets.d.ts.map +1 -0
- package/dist/types/budgets.js +7 -0
- package/dist/types/budgets.js.map +1 -0
- package/dist/types/cli.cjs +2 -11
- package/dist/types/cli.cjs.map +1 -1
- package/dist/types/cli.d.cts +3 -227
- package/dist/types/cli.d.cts.map +1 -1
- package/dist/types/cli.d.ts +3 -227
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/cli.js +2 -11
- package/dist/types/cli.js.map +1 -1
- package/dist/types/core.cjs +6 -1
- package/dist/types/core.cjs.map +1 -1
- package/dist/types/core.d.cts +15 -2
- package/dist/types/core.d.cts.map +1 -1
- package/dist/types/core.d.ts +15 -2
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js +2 -1
- package/dist/types/core.js.map +1 -1
- package/dist/types/index.cjs +5 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +2 -0
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/interfaces.d.cts +19 -8
- package/dist/types/interfaces.d.cts.map +1 -1
- package/dist/types/interfaces.d.ts +19 -8
- package/dist/types/interfaces.d.ts.map +1 -1
- package/dist/types/profiler.cjs +11 -0
- package/dist/types/profiler.cjs.map +1 -0
- package/dist/types/profiler.d.cts +102 -0
- package/dist/types/profiler.d.cts.map +1 -0
- package/dist/types/profiler.d.ts +102 -0
- package/dist/types/profiler.d.ts.map +1 -0
- package/dist/types/profiler.js +10 -0
- package/dist/types/profiler.js.map +1 -0
- package/dist/types/utility.cjs.map +1 -1
- package/dist/types/utility.d.cts +0 -8
- package/dist/types/utility.d.cts.map +1 -1
- package/dist/types/utility.d.ts +0 -8
- package/dist/types/utility.d.ts.map +1 -1
- package/dist/types/utility.js.map +1 -1
- package/dist/utils/identifiers.cjs +32 -0
- package/dist/utils/identifiers.cjs.map +1 -0
- package/dist/utils/identifiers.d.cts +32 -0
- package/dist/utils/identifiers.d.cts.map +1 -0
- package/dist/utils/identifiers.d.ts +32 -0
- package/dist/utils/identifiers.d.ts.map +1 -0
- package/dist/utils/identifiers.js +27 -0
- package/dist/utils/identifiers.js.map +1 -0
- package/dist/utils/package.cjs +40 -0
- package/dist/utils/package.cjs.map +1 -0
- package/dist/utils/package.d.cts +15 -0
- package/dist/utils/package.d.cts.map +1 -0
- package/dist/utils/package.d.ts +15 -0
- package/dist/utils/package.d.ts.map +1 -0
- package/dist/utils/package.js +33 -0
- package/dist/utils/package.js.map +1 -0
- package/dist/utils/type-guards.cjs +48 -0
- package/dist/utils/type-guards.cjs.map +1 -0
- package/dist/utils/type-guards.d.cts +22 -0
- package/dist/utils/type-guards.d.cts.map +1 -0
- package/dist/utils/type-guards.d.ts +22 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +43 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/package.json +18 -19
- package/src/cli/commands/analyze.ts +101 -0
- package/src/cli/commands/baseline.ts +577 -0
- package/src/cli/commands/history.ts +1 -1
- package/src/cli/commands/init.ts +116 -194
- package/src/cli/commands/run.ts +183 -113
- package/src/cli/index.ts +425 -183
- package/src/config/budget-schema.ts +189 -0
- package/src/config/schema.ts +260 -1
- package/src/constants.ts +53 -1
- package/src/core/engine.ts +169 -22
- package/src/core/engines/accurate-engine.ts +195 -44
- package/src/core/engines/tinybench-engine.ts +3 -2
- package/src/core/output-path-resolver.ts +10 -2
- package/src/errors/base.ts +11 -2
- package/src/errors/budget.ts +38 -0
- package/src/errors/index.ts +3 -0
- package/src/index.ts +9 -0
- package/src/reporters/csv.ts +54 -25
- package/src/reporters/human.ts +434 -115
- package/src/reporters/json.ts +26 -71
- package/src/reporters/profile-human.ts +210 -0
- package/src/reporters/simple.ts +88 -54
- package/src/services/baseline-storage.ts +199 -0
- package/src/services/budget-evaluator.ts +182 -0
- package/src/services/config-manager.ts +24 -9
- package/src/services/file-loader.ts +3 -6
- package/src/services/profiler/profile-filter.ts +147 -0
- package/src/services/profiler/profile-parser.ts +194 -0
- package/src/services/profiler/profile-runner.ts +121 -0
- package/src/services/progress-manager.ts +12 -2
- package/src/services/reporter-registry.ts +46 -81
- package/src/types/budgets.ts +180 -0
- package/src/types/cli.ts +5 -238
- package/src/types/core.ts +52 -10
- package/src/types/index.ts +5 -0
- package/src/types/interfaces.ts +24 -6
- package/src/types/profiler.ts +135 -0
- package/src/types/utility.ts +0 -10
- package/src/utils/identifiers.ts +58 -0
- package/src/utils/package.ts +35 -0
- package/src/utils/type-guards.ts +51 -0
package/src/cli/commands/run.ts
CHANGED
|
@@ -7,17 +7,36 @@
|
|
|
7
7
|
|
|
8
8
|
import { resolve } from 'node:path';
|
|
9
9
|
|
|
10
|
-
import type { BenchmarkRun } from '../../types/index.js';
|
|
10
|
+
import type { BenchmarkRun, ModestBenchConfig } from '../../types/index.js';
|
|
11
11
|
import type { CliContext } from '../index.js';
|
|
12
12
|
|
|
13
13
|
import { ErrorCodes } from '../../constants.js';
|
|
14
14
|
import { resolveOutputPath } from '../../core/output-path-resolver.js';
|
|
15
15
|
import {
|
|
16
|
+
type BudgetExceededError,
|
|
16
17
|
InvalidArgumentError,
|
|
17
|
-
type ModestBenchError,
|
|
18
18
|
UnknownReporterError,
|
|
19
19
|
} from '../../errors/index.js';
|
|
20
|
+
import { CsvReporter } from '../../reporters/csv.js';
|
|
21
|
+
import { HumanReporter } from '../../reporters/human.js';
|
|
22
|
+
import { JsonReporter } from '../../reporters/json.js';
|
|
23
|
+
import { SimpleReporter } from '../../reporters/simple.js';
|
|
20
24
|
import { ExitCodes } from '../../types/cli.js';
|
|
25
|
+
import { hasErrorCode, isError } from '../../utils/type-guards.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Default values for the run command
|
|
29
|
+
*
|
|
30
|
+
* These are the command-level defaults used when neither config file nor CLI
|
|
31
|
+
* arguments provide values. They represent sensible defaults for running
|
|
32
|
+
* benchmarks.
|
|
33
|
+
*/
|
|
34
|
+
export const RUN_COMMAND_DEFAULTS = {
|
|
35
|
+
bail: false,
|
|
36
|
+
quiet: false,
|
|
37
|
+
reporters: ['human'],
|
|
38
|
+
verbose: false,
|
|
39
|
+
} as const satisfies Partial<ModestBenchConfig>;
|
|
21
40
|
|
|
22
41
|
/**
|
|
23
42
|
* Run command options interface
|
|
@@ -25,7 +44,7 @@ import { ExitCodes } from '../../types/cli.js';
|
|
|
25
44
|
interface RunOptions {
|
|
26
45
|
bail?: boolean | undefined;
|
|
27
46
|
config?: string | undefined;
|
|
28
|
-
cwd
|
|
47
|
+
cwd?: string;
|
|
29
48
|
engine?: 'accurate' | 'tinybench' | undefined;
|
|
30
49
|
exclude?: string[] | undefined;
|
|
31
50
|
excludeTags?: string[] | undefined;
|
|
@@ -34,10 +53,10 @@ interface RunOptions {
|
|
|
34
53
|
noColor?: boolean | undefined;
|
|
35
54
|
outputDir?: string | undefined;
|
|
36
55
|
outputFile?: string | undefined;
|
|
37
|
-
pattern
|
|
56
|
+
pattern?: string[] | undefined;
|
|
38
57
|
progress?: boolean | undefined;
|
|
39
58
|
quiet?: boolean | undefined;
|
|
40
|
-
reporters
|
|
59
|
+
reporters?: string[] | undefined;
|
|
41
60
|
tags?: string[] | undefined;
|
|
42
61
|
time?: number | undefined;
|
|
43
62
|
timeout?: number | undefined;
|
|
@@ -52,15 +71,8 @@ export const handleRunCommand = async (
|
|
|
52
71
|
context: CliContext,
|
|
53
72
|
options: RunOptions,
|
|
54
73
|
): Promise<number> => {
|
|
55
|
-
// Check if JSON reporter is being used (need quiet output for clean JSON)
|
|
56
|
-
// Only force quiet mode if json is used AND no output directory is specified
|
|
57
|
-
// (i.e., outputting to stdout where we need clean JSON)
|
|
58
|
-
const isUsingJsonReporter = options.reporters?.includes('json') ?? false;
|
|
59
|
-
const shouldBeQuiet =
|
|
60
|
-
options.quiet || (isUsingJsonReporter && !options.outputDir);
|
|
61
74
|
const verbose = options.verbose ?? false;
|
|
62
|
-
|
|
63
|
-
const showCliMessages = verbose && !options.quiet;
|
|
75
|
+
let shouldBeQuiet = options.quiet ?? false; // Will be updated after config loads
|
|
64
76
|
|
|
65
77
|
try {
|
|
66
78
|
// Validate --output-file usage
|
|
@@ -76,22 +88,27 @@ export const handleRunCommand = async (
|
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
// Step 1: Load and merge configuration
|
|
79
|
-
if (showCliMessages) {
|
|
80
|
-
console.error('Loading configuration...');
|
|
81
|
-
}
|
|
82
91
|
const config = await loadConfiguration(context, options);
|
|
83
92
|
|
|
93
|
+
// Check if JSON reporter is being used (need quiet output for clean JSON)
|
|
94
|
+
// Only force quiet mode if json is used AND no output directory is specified
|
|
95
|
+
// (i.e., outputting to stdout where we need clean JSON)
|
|
96
|
+
const isUsingJsonReporter = config.reporters?.includes('json') ?? false;
|
|
97
|
+
const hasOutputDir = !!(options.outputDir || config.outputDir);
|
|
98
|
+
shouldBeQuiet = options.quiet || (isUsingJsonReporter && !hasOutputDir);
|
|
99
|
+
// CLI messages on stderr should only be suppressed by explicit --quiet, not JSON-forced quiet
|
|
100
|
+
const showCliMessages = verbose && !options.quiet;
|
|
101
|
+
|
|
84
102
|
// Step 2: Configure reporters
|
|
85
103
|
if (showCliMessages) {
|
|
86
104
|
console.error('Setting up reporters...');
|
|
87
105
|
}
|
|
88
|
-
const reporters =
|
|
106
|
+
const reporters = setupReporters(
|
|
89
107
|
context,
|
|
90
108
|
config,
|
|
91
|
-
shouldBeQuiet,
|
|
92
109
|
verbose,
|
|
93
110
|
showCliMessages,
|
|
94
|
-
|
|
111
|
+
shouldBeQuiet,
|
|
95
112
|
options.outputDir,
|
|
96
113
|
options.outputFile,
|
|
97
114
|
options.progress,
|
|
@@ -144,7 +161,7 @@ export const handleRunCommand = async (
|
|
|
144
161
|
console.error(` ${error.code}: ${error.message}`);
|
|
145
162
|
}
|
|
146
163
|
}
|
|
147
|
-
return ExitCodes.
|
|
164
|
+
return ExitCodes.VALIDATION_ERROR;
|
|
148
165
|
}
|
|
149
166
|
|
|
150
167
|
// Step 5: Execution phase
|
|
@@ -176,39 +193,66 @@ export const handleRunCommand = async (
|
|
|
176
193
|
|
|
177
194
|
return handleResults(executionResult, options, shouldBeQuiet);
|
|
178
195
|
} catch (error) {
|
|
196
|
+
// Check if error has a code property before accessing it
|
|
197
|
+
const errorCode = hasErrorCode(error) ? error.code : undefined;
|
|
198
|
+
|
|
199
|
+
// Handle budget exceeded error
|
|
200
|
+
if (errorCode === ErrorCodes.BUDGET_EXCEEDED) {
|
|
201
|
+
if (!shouldBeQuiet) {
|
|
202
|
+
const budgetError = error as BudgetExceededError;
|
|
203
|
+
console.error(`\n❌ ${budgetError.message}`);
|
|
204
|
+
if (
|
|
205
|
+
budgetError.budgetSummary &&
|
|
206
|
+
budgetError.budgetSummary.results.length > 0
|
|
207
|
+
) {
|
|
208
|
+
console.error('\nFailed budgets:');
|
|
209
|
+
for (const result of budgetError.budgetSummary.results) {
|
|
210
|
+
if (!result.passed) {
|
|
211
|
+
console.error(` • ${result.taskId}`);
|
|
212
|
+
for (const violation of result.violations) {
|
|
213
|
+
console.error(` ${violation.message}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return ExitCodes.BENCHMARK_FAILURES;
|
|
220
|
+
}
|
|
221
|
+
|
|
179
222
|
// Re-throw CLI errors so yargs fail handler can show help
|
|
180
|
-
if (
|
|
223
|
+
if (errorCode === ErrorCodes.FILE_DISCOVERY_FAILED) {
|
|
181
224
|
throw error;
|
|
182
225
|
}
|
|
183
|
-
if (
|
|
226
|
+
if (errorCode === ErrorCodes.CLI_INVALID_ARGUMENT) {
|
|
184
227
|
throw error;
|
|
185
228
|
}
|
|
186
229
|
|
|
187
230
|
if (!shouldBeQuiet) {
|
|
188
|
-
console.error(
|
|
189
|
-
`Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
190
|
-
);
|
|
231
|
+
console.error(`Error: ${isError(error) ? error.message : String(error)}`);
|
|
191
232
|
}
|
|
192
233
|
|
|
193
|
-
// Return appropriate exit code based on error
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
234
|
+
// Return appropriate exit code based on error code
|
|
235
|
+
if (
|
|
236
|
+
errorCode === ErrorCodes.CONFIG_LOAD_FAILED ||
|
|
237
|
+
errorCode === ErrorCodes.CONFIG_NOT_FOUND ||
|
|
238
|
+
errorCode === ErrorCodes.CONFIG_VALIDATION_FAILED ||
|
|
239
|
+
errorCode === ErrorCodes.CONFIG_UNSUPPORTED_FORMAT
|
|
240
|
+
) {
|
|
241
|
+
return ExitCodes.CONFIG_ERROR;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (errorCode === ErrorCodes.FILE_DISCOVERY_FAILED) {
|
|
245
|
+
return ExitCodes.DISCOVERY_ERROR;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Fallback: check error message for cases where proper error types aren't thrown yet
|
|
249
|
+
if (isError(error)) {
|
|
250
|
+
if (error.message.includes('No benchmark files found')) {
|
|
251
|
+
return ExitCodes.DISCOVERY_ERROR;
|
|
208
252
|
}
|
|
209
253
|
}
|
|
210
254
|
|
|
211
|
-
return ExitCodes.
|
|
255
|
+
return ExitCodes.BENCHMARK_FAILURES;
|
|
212
256
|
}
|
|
213
257
|
};
|
|
214
258
|
|
|
@@ -230,11 +274,11 @@ const handleResults = (
|
|
|
230
274
|
if (executionResult && executionResult.summary) {
|
|
231
275
|
// Return error if there are failed tasks OR file-level errors
|
|
232
276
|
return executionResult.summary.failedTasks > 0 || hasFileErrors
|
|
233
|
-
? ExitCodes.
|
|
234
|
-
: ExitCodes.
|
|
277
|
+
? ExitCodes.BENCHMARK_FAILURES
|
|
278
|
+
: ExitCodes.SUCCESS;
|
|
235
279
|
}
|
|
236
280
|
|
|
237
|
-
return ExitCodes.
|
|
281
|
+
return ExitCodes.SUCCESS;
|
|
238
282
|
};
|
|
239
283
|
|
|
240
284
|
/**
|
|
@@ -246,17 +290,20 @@ const loadConfiguration = async (context: CliContext, options: RunOptions) => {
|
|
|
246
290
|
const cliArgs: Record<string, unknown> = {};
|
|
247
291
|
|
|
248
292
|
// Map CLI arguments to config properties
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
293
|
+
// Only pass pattern if explicitly provided (non-empty)
|
|
294
|
+
// Empty array means no CLI pattern, so config file or defaults should be used
|
|
295
|
+
if (options.pattern !== undefined && options.pattern.length > 0) {
|
|
252
296
|
cliArgs.pattern =
|
|
253
297
|
options.pattern.length === 1 ? options.pattern[0] : options.pattern;
|
|
254
298
|
}
|
|
255
|
-
if (options.reporters) {
|
|
299
|
+
if (options.reporters && options.reporters.length > 0) {
|
|
256
300
|
cliArgs.reporters = options.reporters;
|
|
257
301
|
}
|
|
258
302
|
if (options.outputDir) {
|
|
259
|
-
cliArgs.outputDir = resolve(
|
|
303
|
+
cliArgs.outputDir = resolve(
|
|
304
|
+
options.cwd ?? process.cwd(),
|
|
305
|
+
options.outputDir,
|
|
306
|
+
);
|
|
260
307
|
}
|
|
261
308
|
if (options.iterations) {
|
|
262
309
|
cliArgs.iterations = options.iterations;
|
|
@@ -270,7 +317,7 @@ const loadConfiguration = async (context: CliContext, options: RunOptions) => {
|
|
|
270
317
|
if (options.bail !== undefined) {
|
|
271
318
|
cliArgs.bail = options.bail;
|
|
272
319
|
}
|
|
273
|
-
if (options.exclude) {
|
|
320
|
+
if (options.exclude && options.exclude.length > 0) {
|
|
274
321
|
cliArgs.exclude = options.exclude;
|
|
275
322
|
}
|
|
276
323
|
if (options.timeout) {
|
|
@@ -282,24 +329,30 @@ const loadConfiguration = async (context: CliContext, options: RunOptions) => {
|
|
|
282
329
|
if (options.verbose !== undefined) {
|
|
283
330
|
cliArgs.verbose = options.verbose;
|
|
284
331
|
}
|
|
285
|
-
if (options.tags) {
|
|
332
|
+
if (options.tags && options.tags.length > 0) {
|
|
286
333
|
cliArgs.tags = options.tags;
|
|
287
334
|
}
|
|
288
|
-
if (options.excludeTags) {
|
|
335
|
+
if (options.excludeTags && options.excludeTags.length > 0) {
|
|
289
336
|
cliArgs.excludeTags = options.excludeTags;
|
|
290
337
|
}
|
|
291
338
|
|
|
292
339
|
// Load configuration with CLI argument precedence
|
|
293
|
-
|
|
340
|
+
// Pass command defaults as the base layer
|
|
341
|
+
const config = await context.configManager.load(
|
|
342
|
+
options.config,
|
|
343
|
+
cliArgs,
|
|
344
|
+
RUN_COMMAND_DEFAULTS,
|
|
345
|
+
);
|
|
294
346
|
|
|
295
347
|
return config;
|
|
296
348
|
} catch (error) {
|
|
297
349
|
// Re-throw our custom errors
|
|
298
|
-
|
|
350
|
+
const errorCode = hasErrorCode(error) ? error.code : undefined;
|
|
351
|
+
if (errorCode === ErrorCodes.CONFIG_LOAD_FAILED) {
|
|
299
352
|
throw error;
|
|
300
353
|
}
|
|
301
354
|
throw new InvalidArgumentError(
|
|
302
|
-
`Configuration error: ${error
|
|
355
|
+
`Configuration error: ${isError(error) ? error.message : String(error)}`,
|
|
303
356
|
{ cause: error },
|
|
304
357
|
);
|
|
305
358
|
}
|
|
@@ -308,10 +361,9 @@ const loadConfiguration = async (context: CliContext, options: RunOptions) => {
|
|
|
308
361
|
/**
|
|
309
362
|
* Setup and configure reporters based on configuration
|
|
310
363
|
*/
|
|
311
|
-
const setupReporters =
|
|
364
|
+
const setupReporters = (
|
|
312
365
|
context: CliContext,
|
|
313
366
|
config: { outputDir?: string; reporters?: string[] },
|
|
314
|
-
shouldBeQuiet: boolean,
|
|
315
367
|
isVerbose: boolean,
|
|
316
368
|
showCliMessages: boolean,
|
|
317
369
|
explicitQuiet: boolean,
|
|
@@ -321,70 +373,87 @@ const setupReporters = async (
|
|
|
321
373
|
) => {
|
|
322
374
|
try {
|
|
323
375
|
const reporters = [];
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
// Dynamically import reporters for proper configuration
|
|
327
|
-
const { HumanReporter } = await import('../../reporters/human.js');
|
|
328
|
-
const { JsonReporter } = await import('../../reporters/json.js');
|
|
329
|
-
const { CsvReporter } = await import('../../reporters/csv.js');
|
|
330
|
-
const { SimpleReporter } = await import('../../reporters/simple.js');
|
|
376
|
+
// Dedupe requested reporters
|
|
377
|
+
const requestedReporters = [...new Set(config.reporters || ['human'])];
|
|
331
378
|
|
|
332
|
-
//
|
|
333
|
-
//
|
|
379
|
+
// Use output directory from CLI flag, config file, or undefined
|
|
380
|
+
// CLI flag takes precedence over config file
|
|
334
381
|
const outputDir = explicitOutputDir
|
|
335
382
|
? resolve(explicitOutputDir)
|
|
336
|
-
:
|
|
383
|
+
: config.outputDir
|
|
384
|
+
? resolve(config.outputDir)
|
|
385
|
+
: undefined;
|
|
386
|
+
|
|
387
|
+
// Built-in reporter names for error messages
|
|
388
|
+
const builtInReporters = ['human', 'json', 'csv', 'simple'];
|
|
337
389
|
|
|
338
390
|
for (const reporterName of requestedReporters) {
|
|
339
391
|
let reporter;
|
|
340
392
|
|
|
341
393
|
// Create reporter instances with output path configuration
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
});
|
|
349
|
-
} else if (reporterName === 'json') {
|
|
350
|
-
const outputPath = resolveOutputPath(
|
|
351
|
-
outputDir,
|
|
352
|
-
explicitOutputFile,
|
|
353
|
-
'results.json',
|
|
354
|
-
);
|
|
355
|
-
reporter = new JsonReporter({
|
|
356
|
-
...(outputPath ? { outputPath } : {}),
|
|
357
|
-
prettyPrint: true,
|
|
358
|
-
quiet: shouldBeQuiet, // JSON uses shouldBeQuiet to avoid polluting stdout
|
|
359
|
-
verbose: isVerbose,
|
|
360
|
-
});
|
|
361
|
-
} else if (reporterName === 'csv') {
|
|
362
|
-
const outputPath = resolveOutputPath(
|
|
363
|
-
outputDir,
|
|
364
|
-
explicitOutputFile,
|
|
365
|
-
'results.csv',
|
|
366
|
-
);
|
|
367
|
-
reporter = new CsvReporter({
|
|
368
|
-
includeHeaders: true,
|
|
369
|
-
includeMetadata: true,
|
|
370
|
-
...(outputPath ? { outputPath } : {}),
|
|
371
|
-
quiet: explicitQuiet, // Only applies explicit --quiet flag; CSV output can coexist with progress messages on different streams
|
|
372
|
-
verbose: isVerbose,
|
|
373
|
-
});
|
|
374
|
-
} else if (reporterName === 'simple') {
|
|
375
|
-
reporter = new SimpleReporter({
|
|
376
|
-
quiet: explicitQuiet,
|
|
377
|
-
verbose: isVerbose,
|
|
378
|
-
});
|
|
379
|
-
} else {
|
|
380
|
-
// Fall back to registry for custom reporters
|
|
381
|
-
reporter = context.reporterRegistry.get(reporterName);
|
|
382
|
-
if (!reporter) {
|
|
383
|
-
const availableReporters = ['human', 'json', 'csv', 'simple'];
|
|
384
|
-
throw new UnknownReporterError(
|
|
385
|
-
`Unknown reporter: ${reporterName}. Available: ${availableReporters.join(', ')}`,
|
|
394
|
+
switch (reporterName) {
|
|
395
|
+
case 'csv': {
|
|
396
|
+
const outputPath = resolveOutputPath(
|
|
397
|
+
outputDir,
|
|
398
|
+
explicitOutputFile,
|
|
399
|
+
'results.csv',
|
|
386
400
|
);
|
|
401
|
+
reporter = new CsvReporter({
|
|
402
|
+
includeHeaders: true,
|
|
403
|
+
includeMetadata: true,
|
|
404
|
+
...(outputPath ? { outputPath } : {}),
|
|
405
|
+
quiet: explicitQuiet, // Only applies explicit --quiet flag; CSV output can coexist with progress messages on different streams
|
|
406
|
+
verbose: isVerbose,
|
|
407
|
+
});
|
|
408
|
+
break;
|
|
387
409
|
}
|
|
410
|
+
|
|
411
|
+
case 'human':
|
|
412
|
+
reporter = new HumanReporter({
|
|
413
|
+
color: true,
|
|
414
|
+
progress: progressOption ?? true,
|
|
415
|
+
quiet: explicitQuiet, // Only applies explicit --quiet flag; JSON reporter forcing quiet mode does not affect HumanReporter progress output
|
|
416
|
+
verbose: isVerbose,
|
|
417
|
+
});
|
|
418
|
+
break;
|
|
419
|
+
|
|
420
|
+
case 'json': {
|
|
421
|
+
const outputPath = resolveOutputPath(
|
|
422
|
+
outputDir,
|
|
423
|
+
explicitOutputFile,
|
|
424
|
+
'results.json',
|
|
425
|
+
);
|
|
426
|
+
reporter = new JsonReporter({
|
|
427
|
+
...(outputPath ? { outputPath } : {}),
|
|
428
|
+
prettyPrint: true,
|
|
429
|
+
});
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
case 'simple':
|
|
434
|
+
reporter = new SimpleReporter({
|
|
435
|
+
quiet: explicitQuiet,
|
|
436
|
+
verbose: isVerbose,
|
|
437
|
+
});
|
|
438
|
+
break;
|
|
439
|
+
|
|
440
|
+
default:
|
|
441
|
+
// Fall back to registry for custom reporters
|
|
442
|
+
reporter = context.reporterRegistry.get(reporterName);
|
|
443
|
+
if (!reporter) {
|
|
444
|
+
// Combine built-in reporters with registered custom reporters
|
|
445
|
+
const registeredReporters = Object.keys(
|
|
446
|
+
context.reporterRegistry.getAll(),
|
|
447
|
+
);
|
|
448
|
+
const availableReporters = [
|
|
449
|
+
...builtInReporters,
|
|
450
|
+
...registeredReporters,
|
|
451
|
+
];
|
|
452
|
+
throw new UnknownReporterError(
|
|
453
|
+
`Unknown reporter: ${reporterName}. Available: ${availableReporters.join(', ')}`,
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
break;
|
|
388
457
|
}
|
|
389
458
|
|
|
390
459
|
reporters.push(reporter);
|
|
@@ -397,11 +466,12 @@ const setupReporters = async (
|
|
|
397
466
|
return reporters;
|
|
398
467
|
} catch (error) {
|
|
399
468
|
// Re-throw our custom errors
|
|
400
|
-
|
|
469
|
+
const errorCode = hasErrorCode(error) ? error.code : undefined;
|
|
470
|
+
if (errorCode === ErrorCodes.REPORTER_UNKNOWN) {
|
|
401
471
|
throw error;
|
|
402
472
|
}
|
|
403
473
|
throw new InvalidArgumentError(
|
|
404
|
-
`Reporter setup error: ${error
|
|
474
|
+
`Reporter setup error: ${isError(error) ? error.message : String(error)}`,
|
|
405
475
|
{ cause: error },
|
|
406
476
|
);
|
|
407
477
|
}
|