modestbench 0.1.0 → 0.3.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 +31 -0
- package/README.md +162 -57
- package/dist/bootstrap.cjs +10 -10
- package/dist/bootstrap.cjs.map +1 -1
- package/dist/bootstrap.d.cts.map +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +5 -5
- package/dist/bootstrap.js.map +1 -1
- 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.cjs +108 -266
- package/dist/cli/commands/history.cjs.map +1 -1
- package/dist/cli/commands/history.d.cts +75 -12
- package/dist/cli/commands/history.d.cts.map +1 -1
- package/dist/cli/commands/history.d.ts +75 -12
- package/dist/cli/commands/history.d.ts.map +1 -1
- package/dist/cli/commands/history.js +105 -268
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/init.cjs +88 -155
- 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 +88 -155
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.cjs +143 -112
- package/dist/cli/commands/run.cjs.map +1 -1
- package/dist/cli/commands/run.d.cts +17 -3
- package/dist/cli/commands/run.d.cts.map +1 -1
- package/dist/cli/commands/run.d.ts +17 -3
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +142 -78
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.cjs +671 -266
- 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 +664 -259
- 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 +104 -15
- package/dist/core/engine.cjs.map +1 -1
- package/dist/core/engine.d.cts +7 -4
- package/dist/core/engine.d.cts.map +1 -1
- package/dist/core/engine.d.ts +7 -4
- package/dist/core/engine.d.ts.map +1 -1
- package/dist/core/engine.js +105 -16
- package/dist/core/engine.js.map +1 -1
- package/dist/core/output-path-resolver.cjs +41 -0
- package/dist/core/output-path-resolver.cjs.map +1 -0
- package/dist/core/output-path-resolver.d.cts +10 -0
- package/dist/core/output-path-resolver.d.cts.map +1 -0
- package/dist/core/output-path-resolver.d.ts +10 -0
- package/dist/core/output-path-resolver.d.ts.map +1 -0
- package/dist/core/output-path-resolver.js +37 -0
- package/dist/core/output-path-resolver.js.map +1 -0
- 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/formatters/history/base.cjs +9 -0
- package/dist/formatters/history/base.cjs.map +1 -0
- package/dist/formatters/history/base.d.cts +26 -0
- package/dist/formatters/history/base.d.cts.map +1 -0
- package/dist/formatters/history/base.d.ts +26 -0
- package/dist/formatters/history/base.d.ts.map +1 -0
- package/dist/formatters/history/base.js +8 -0
- package/dist/formatters/history/base.js.map +1 -0
- package/dist/formatters/history/compare.cjs +127 -0
- package/dist/formatters/history/compare.cjs.map +1 -0
- package/dist/formatters/history/compare.d.cts +21 -0
- package/dist/formatters/history/compare.d.cts.map +1 -0
- package/dist/formatters/history/compare.d.ts +21 -0
- package/dist/formatters/history/compare.d.ts.map +1 -0
- package/dist/formatters/history/compare.js +123 -0
- package/dist/formatters/history/compare.js.map +1 -0
- package/dist/formatters/history/list.cjs +74 -0
- package/dist/formatters/history/list.cjs.map +1 -0
- package/dist/formatters/history/list.d.cts +25 -0
- package/dist/formatters/history/list.d.cts.map +1 -0
- package/dist/formatters/history/list.d.ts +25 -0
- package/dist/formatters/history/list.d.ts.map +1 -0
- package/dist/formatters/history/list.js +70 -0
- package/dist/formatters/history/list.js.map +1 -0
- package/dist/formatters/history/show.cjs +98 -0
- package/dist/formatters/history/show.cjs.map +1 -0
- package/dist/formatters/history/show.d.cts +21 -0
- package/dist/formatters/history/show.d.cts.map +1 -0
- package/dist/formatters/history/show.d.ts +21 -0
- package/dist/formatters/history/show.d.ts.map +1 -0
- package/dist/formatters/history/show.js +94 -0
- package/dist/formatters/history/show.js.map +1 -0
- package/dist/formatters/history/trends.cjs +194 -0
- package/dist/formatters/history/trends.cjs.map +1 -0
- package/dist/formatters/history/trends.d.cts +22 -0
- package/dist/formatters/history/trends.d.cts.map +1 -0
- package/dist/formatters/history/trends.d.ts +22 -0
- package/dist/formatters/history/trends.d.ts.map +1 -0
- package/dist/formatters/history/trends.js +190 -0
- package/dist/formatters/history/trends.js.map +1 -0
- package/dist/formatters/history/visualization.cjs +79 -0
- package/dist/formatters/history/visualization.cjs.map +1 -0
- package/dist/formatters/history/visualization.d.cts +24 -0
- package/dist/formatters/history/visualization.d.cts.map +1 -0
- package/dist/formatters/history/visualization.d.ts +24 -0
- package/dist/formatters/history/visualization.d.ts.map +1 -0
- package/dist/formatters/history/visualization.js +74 -0
- package/dist/formatters/history/visualization.js.map +1 -0
- package/dist/index.cjs +27 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/reporters/csv.cjs +39 -19
- package/dist/reporters/csv.cjs.map +1 -1
- package/dist/reporters/csv.d.cts +4 -7
- package/dist/reporters/csv.d.cts.map +1 -1
- package/dist/reporters/csv.d.ts +4 -7
- package/dist/reporters/csv.d.ts.map +1 -1
- package/dist/reporters/csv.js +38 -18
- package/dist/reporters/csv.js.map +1 -1
- package/dist/reporters/human.cjs +87 -99
- package/dist/reporters/human.cjs.map +1 -1
- package/dist/reporters/human.d.cts +15 -14
- package/dist/reporters/human.d.cts.map +1 -1
- package/dist/reporters/human.d.ts +15 -14
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +68 -80
- package/dist/reporters/human.js.map +1 -1
- package/dist/reporters/json.cjs +25 -50
- package/dist/reporters/json.cjs.map +1 -1
- package/dist/reporters/json.d.cts +3 -29
- package/dist/reporters/json.d.cts.map +1 -1
- package/dist/reporters/json.d.ts +3 -29
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +26 -51
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/profile-human.cjs +149 -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 +142 -0
- package/dist/reporters/profile-human.js.map +1 -0
- package/dist/reporters/simple.cjs +66 -46
- package/dist/reporters/simple.cjs.map +1 -1
- package/dist/reporters/simple.d.cts +15 -15
- package/dist/reporters/simple.d.cts.map +1 -1
- package/dist/reporters/simple.d.ts +15 -15
- package/dist/reporters/simple.d.ts.map +1 -1
- package/dist/reporters/simple.js +65 -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/{config/manager.cjs → services/config-manager.cjs} +25 -11
- package/dist/services/config-manager.cjs.map +1 -0
- package/dist/{config/manager.d.cts → services/config-manager.d.cts} +7 -2
- package/dist/services/config-manager.d.cts.map +1 -0
- package/dist/{config/manager.d.ts → services/config-manager.d.ts} +7 -2
- package/dist/services/config-manager.d.ts.map +1 -0
- package/dist/{config/manager.js → services/config-manager.js} +25 -11
- package/dist/services/config-manager.js.map +1 -0
- package/dist/{core/loader.cjs → services/file-loader.cjs} +5 -8
- package/dist/services/file-loader.cjs.map +1 -0
- package/dist/{core/loader.d.cts → services/file-loader.d.cts} +1 -1
- package/dist/services/file-loader.d.cts.map +1 -0
- package/dist/{core/loader.d.ts → services/file-loader.d.ts} +1 -1
- package/dist/services/file-loader.d.ts.map +1 -0
- package/dist/{core/loader.js → services/file-loader.js} +5 -8
- package/dist/services/file-loader.js.map +1 -0
- package/dist/services/history/comparison.cjs +124 -0
- package/dist/services/history/comparison.cjs.map +1 -0
- package/dist/services/history/comparison.d.cts +18 -0
- package/dist/services/history/comparison.d.cts.map +1 -0
- package/dist/services/history/comparison.d.ts +18 -0
- package/dist/services/history/comparison.d.ts.map +1 -0
- package/dist/services/history/comparison.js +120 -0
- package/dist/services/history/comparison.js.map +1 -0
- package/dist/services/history/models.cjs +9 -0
- package/dist/services/history/models.cjs.map +1 -0
- package/dist/services/history/models.d.cts +139 -0
- package/dist/services/history/models.d.cts.map +1 -0
- package/dist/services/history/models.d.ts +139 -0
- package/dist/services/history/models.d.ts.map +1 -0
- package/dist/services/history/models.js +8 -0
- package/dist/services/history/models.js.map +1 -0
- package/dist/services/history/query.cjs +97 -0
- package/dist/services/history/query.cjs.map +1 -0
- package/dist/services/history/query.d.cts +38 -0
- package/dist/services/history/query.d.cts.map +1 -0
- package/dist/services/history/query.d.ts +38 -0
- package/dist/services/history/query.d.ts.map +1 -0
- package/dist/services/history/query.js +92 -0
- package/dist/services/history/query.js.map +1 -0
- package/dist/services/history/trend-analysis.cjs +187 -0
- package/dist/services/history/trend-analysis.cjs.map +1 -0
- package/dist/services/history/trend-analysis.d.cts +34 -0
- package/dist/services/history/trend-analysis.d.cts.map +1 -0
- package/dist/services/history/trend-analysis.d.ts +34 -0
- package/dist/services/history/trend-analysis.d.ts.map +1 -0
- package/dist/services/history/trend-analysis.js +179 -0
- package/dist/services/history/trend-analysis.js.map +1 -0
- package/dist/{storage/history.cjs → services/history-storage.cjs} +1 -1
- package/dist/services/history-storage.cjs.map +1 -0
- package/dist/{storage/history.d.cts → services/history-storage.d.cts} +1 -1
- package/dist/services/history-storage.d.cts.map +1 -0
- package/dist/{storage/history.d.ts → services/history-storage.d.ts} +1 -1
- package/dist/services/history-storage.d.ts.map +1 -0
- package/dist/{storage/history.js → services/history-storage.js} +1 -1
- package/dist/services/history-storage.js.map +1 -0
- package/dist/services/profiler/profile-filter.cjs +113 -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 +109 -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/{progress/manager.cjs → services/progress-manager.cjs} +1 -1
- package/dist/services/progress-manager.cjs.map +1 -0
- package/dist/{progress/manager.d.cts → services/progress-manager.d.cts} +1 -1
- package/dist/services/progress-manager.d.cts.map +1 -0
- package/dist/{progress/manager.d.ts → services/progress-manager.d.ts} +1 -1
- package/dist/services/progress-manager.d.ts.map +1 -0
- package/dist/{progress/manager.js → services/progress-manager.js} +1 -1
- package/dist/services/progress-manager.js.map +1 -0
- package/dist/{reporters/registry.cjs → services/reporter-registry.cjs} +19 -25
- package/dist/services/reporter-registry.cjs.map +1 -0
- package/dist/{reporters/registry.d.cts → services/reporter-registry.d.cts} +19 -41
- package/dist/services/reporter-registry.d.cts.map +1 -0
- package/dist/{reporters/registry.d.ts → services/reporter-registry.d.ts} +19 -41
- package/dist/services/reporter-registry.d.ts.map +1 -0
- package/dist/{reporters/registry.js → services/reporter-registry.js} +19 -25
- package/dist/services/reporter-registry.js.map +1 -0
- 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 -224
- package/dist/types/cli.d.cts.map +1 -1
- package/dist/types/cli.d.ts +3 -224
- 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 +13 -2
- package/dist/types/core.d.cts.map +1 -1
- package/dist/types/core.d.ts +13 -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 +15 -8
- package/dist/types/interfaces.d.cts.map +1 -1
- package/dist/types/interfaces.d.ts +15 -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 +100 -0
- package/dist/types/profiler.d.cts.map +1 -0
- package/dist/types/profiler.d.ts +100 -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/ansi.cjs +61 -0
- package/dist/utils/ansi.cjs.map +1 -0
- package/dist/utils/ansi.d.cts +53 -0
- package/dist/utils/ansi.d.cts.map +1 -0
- package/dist/utils/ansi.d.ts +53 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +57 -0
- package/dist/utils/ansi.js.map +1 -0
- 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 +14 -13
- package/src/bootstrap.ts +5 -5
- package/src/cli/commands/analyze.ts +101 -0
- package/src/cli/commands/baseline.ts +577 -0
- package/src/cli/commands/history.ts +194 -342
- package/src/cli/commands/init.ts +105 -183
- package/src/cli/commands/run.ts +186 -88
- package/src/cli/index.ts +731 -234
- 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 +153 -14
- package/src/core/output-path-resolver.ts +46 -0
- package/src/errors/base.ts +11 -2
- package/src/errors/budget.ts +38 -0
- package/src/errors/index.ts +3 -0
- package/src/formatters/history/base.ts +28 -0
- package/src/formatters/history/compare.ts +186 -0
- package/src/formatters/history/list.ts +101 -0
- package/src/formatters/history/show.ts +155 -0
- package/src/formatters/history/trends.ts +281 -0
- package/src/formatters/history/visualization.ts +93 -0
- package/src/index.ts +17 -12
- package/src/reporters/csv.ts +55 -26
- package/src/reporters/human.ts +90 -89
- package/src/reporters/json.ts +27 -72
- package/src/reporters/profile-human.ts +204 -0
- package/src/reporters/simple.ts +85 -54
- package/src/services/baseline-storage.ts +199 -0
- package/src/services/budget-evaluator.ts +182 -0
- package/src/{config/manager.ts → services/config-manager.ts} +24 -9
- package/src/{core/loader.ts → services/file-loader.ts} +4 -7
- package/src/services/history/comparison.ts +130 -0
- package/src/services/history/models.ts +148 -0
- package/src/services/history/query.ts +116 -0
- package/src/services/history/trend-analysis.ts +238 -0
- package/src/services/profiler/profile-filter.ts +143 -0
- package/src/services/profiler/profile-parser.ts +194 -0
- package/src/services/profiler/profile-runner.ts +121 -0
- package/src/{reporters/registry.ts → services/reporter-registry.ts} +46 -81
- package/src/types/budgets.ts +180 -0
- package/src/types/cli.ts +5 -235
- package/src/types/core.ts +50 -10
- package/src/types/index.ts +5 -0
- package/src/types/interfaces.ts +16 -6
- package/src/types/profiler.ts +132 -0
- package/src/types/utility.ts +0 -10
- package/src/utils/ansi.ts +59 -0
- package/src/utils/identifiers.ts +58 -0
- package/src/utils/package.ts +35 -0
- package/src/utils/type-guards.ts +51 -0
- package/dist/config/manager.cjs.map +0 -1
- package/dist/config/manager.d.cts.map +0 -1
- package/dist/config/manager.d.ts.map +0 -1
- package/dist/config/manager.js.map +0 -1
- package/dist/core/loader.cjs.map +0 -1
- package/dist/core/loader.d.cts.map +0 -1
- package/dist/core/loader.d.ts.map +0 -1
- package/dist/core/loader.js.map +0 -1
- package/dist/progress/manager.cjs.map +0 -1
- package/dist/progress/manager.d.cts.map +0 -1
- package/dist/progress/manager.d.ts.map +0 -1
- package/dist/progress/manager.js.map +0 -1
- package/dist/reporters/registry.cjs.map +0 -1
- package/dist/reporters/registry.d.cts.map +0 -1
- package/dist/reporters/registry.d.ts.map +0 -1
- package/dist/reporters/registry.js.map +0 -1
- package/dist/storage/history.cjs.map +0 -1
- package/dist/storage/history.d.cts.map +0 -1
- package/dist/storage/history.d.ts.map +0 -1
- package/dist/storage/history.js.map +0 -1
- /package/src/{storage/history.ts → services/history-storage.ts} +0 -0
- /package/src/{progress/manager.ts → services/progress-manager.ts} +0 -0
package/src/reporters/csv.ts
CHANGED
|
@@ -11,20 +11,24 @@ import { dirname } from 'node:path';
|
|
|
11
11
|
|
|
12
12
|
import type {
|
|
13
13
|
BenchmarkRun,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
BudgetResult,
|
|
15
|
+
BudgetSummary,
|
|
16
|
+
TaskId,
|
|
17
17
|
TaskResult,
|
|
18
18
|
} from '../types/index.js';
|
|
19
19
|
|
|
20
20
|
import { ReporterOutputError } from '../errors/index.js';
|
|
21
|
-
import { BaseReporter } from '
|
|
21
|
+
import { BaseReporter } from '../services/reporter-registry.js';
|
|
22
|
+
import { createTaskId } from '../types/index.js';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* CSV column definitions for task results
|
|
25
26
|
*/
|
|
26
27
|
interface CsvRow {
|
|
27
28
|
readonly arch: string;
|
|
29
|
+
/** Budget passed: 1 (pass), 0 (fail), undefined (no budget) */
|
|
30
|
+
readonly budgetPassed?: number | undefined;
|
|
31
|
+
readonly budgetViolations?: string | undefined;
|
|
28
32
|
readonly ciProvider?: string | undefined;
|
|
29
33
|
readonly cpuCores: number;
|
|
30
34
|
readonly cpuModel: string;
|
|
@@ -54,6 +58,8 @@ interface CsvRow {
|
|
|
54
58
|
* CSV reporter for structured tabular output
|
|
55
59
|
*/
|
|
56
60
|
export class CsvReporter extends BaseReporter {
|
|
61
|
+
private budgetResults: Map<TaskId, BudgetResult> = new Map();
|
|
62
|
+
|
|
57
63
|
private currentFile = '';
|
|
58
64
|
|
|
59
65
|
private currentRun?: BenchmarkRun;
|
|
@@ -68,8 +74,6 @@ export class CsvReporter extends BaseReporter {
|
|
|
68
74
|
|
|
69
75
|
private readonly outputPath?: string | undefined;
|
|
70
76
|
|
|
71
|
-
private readonly quiet: boolean;
|
|
72
|
-
|
|
73
77
|
private readonly quote: string;
|
|
74
78
|
|
|
75
79
|
private rows: CsvRow[] = [];
|
|
@@ -92,7 +96,6 @@ export class CsvReporter extends BaseReporter {
|
|
|
92
96
|
this.includeMetadata = options.includeMetadata ?? true;
|
|
93
97
|
this.delimiter = options.delimiter ?? ',';
|
|
94
98
|
this.quote = options.quote ?? '"';
|
|
95
|
-
this.quiet = options.quiet ?? false;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
/**
|
|
@@ -137,6 +140,31 @@ export class CsvReporter extends BaseReporter {
|
|
|
137
140
|
return this.includeMetadata;
|
|
138
141
|
}
|
|
139
142
|
|
|
143
|
+
onBudgetResult(summary: BudgetSummary): void {
|
|
144
|
+
// Store budget results indexed by taskId
|
|
145
|
+
for (const result of summary.results) {
|
|
146
|
+
this.budgetResults.set(result.taskId, result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Update existing rows with budget data (since onTaskResult is called before onBudgetResult)
|
|
150
|
+
for (const row of this.rows) {
|
|
151
|
+
// row.file is already relative to cwd
|
|
152
|
+
const taskId = createTaskId(row.file, row.suite, row.task);
|
|
153
|
+
const budgetResult = this.budgetResults.get(taskId);
|
|
154
|
+
if (budgetResult) {
|
|
155
|
+
// Need to cast to mutable to update readonly properties
|
|
156
|
+
const mutableRow = row as {
|
|
157
|
+
budgetPassed?: number;
|
|
158
|
+
budgetViolations?: string;
|
|
159
|
+
};
|
|
160
|
+
mutableRow.budgetPassed = budgetResult.passed ? 1 : 0;
|
|
161
|
+
mutableRow.budgetViolations = budgetResult.violations
|
|
162
|
+
.map((v) => v.type)
|
|
163
|
+
.join('; ');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
140
168
|
async onEnd(_run: BenchmarkRun): Promise<void> {
|
|
141
169
|
const csvContent = this.generateCsv();
|
|
142
170
|
|
|
@@ -151,27 +179,15 @@ export class CsvReporter extends BaseReporter {
|
|
|
151
179
|
console.error('CSV Reporter Error:', error.message);
|
|
152
180
|
}
|
|
153
181
|
|
|
154
|
-
onFileEnd(_result: FileResult): void {
|
|
155
|
-
// No-op for CSV reporter
|
|
156
|
-
}
|
|
157
|
-
|
|
158
182
|
onFileStart(file: string): void {
|
|
159
183
|
this.currentFile = file;
|
|
160
184
|
}
|
|
161
185
|
|
|
162
|
-
onProgress(_state: ProgressState): void {
|
|
163
|
-
// No-op for CSV reporter
|
|
164
|
-
}
|
|
165
|
-
|
|
166
186
|
onStart(run: BenchmarkRun): void {
|
|
167
187
|
this.currentRun = run;
|
|
168
188
|
this.rows = [];
|
|
169
189
|
}
|
|
170
190
|
|
|
171
|
-
onSuiteEnd(_result: SuiteResult): void {
|
|
172
|
-
// No-op for CSV reporter
|
|
173
|
-
}
|
|
174
|
-
|
|
175
191
|
onSuiteStart(suite: string): void {
|
|
176
192
|
this.currentSuite = suite;
|
|
177
193
|
}
|
|
@@ -181,8 +197,21 @@ export class CsvReporter extends BaseReporter {
|
|
|
181
197
|
return;
|
|
182
198
|
}
|
|
183
199
|
|
|
200
|
+
// Look up budget result for this task
|
|
201
|
+
// this.currentFile is already relative to cwd (comes from engine)
|
|
202
|
+
const taskId = createTaskId(
|
|
203
|
+
this.currentFile,
|
|
204
|
+
this.currentSuite,
|
|
205
|
+
result.name,
|
|
206
|
+
);
|
|
207
|
+
const budgetResult = this.budgetResults.get(taskId);
|
|
208
|
+
|
|
184
209
|
const row: CsvRow = {
|
|
185
210
|
arch: this.currentRun.environment.arch,
|
|
211
|
+
budgetPassed: budgetResult ? (budgetResult.passed ? 1 : 0) : undefined,
|
|
212
|
+
budgetViolations: budgetResult
|
|
213
|
+
? budgetResult.violations.map((v) => v.type).join('; ')
|
|
214
|
+
: undefined,
|
|
186
215
|
ciProvider: this.currentRun.ci?.provider,
|
|
187
216
|
cpuCores: this.currentRun.environment.cpu.cores,
|
|
188
217
|
cpuModel: this.currentRun.environment.cpu.model,
|
|
@@ -211,10 +240,6 @@ export class CsvReporter extends BaseReporter {
|
|
|
211
240
|
this.rows.push(row);
|
|
212
241
|
}
|
|
213
242
|
|
|
214
|
-
onTaskStart(_task: string): void {
|
|
215
|
-
// No-op for CSV reporter
|
|
216
|
-
}
|
|
217
|
-
|
|
218
243
|
/**
|
|
219
244
|
* Escape a field value for CSV format
|
|
220
245
|
*/
|
|
@@ -277,6 +302,8 @@ export class CsvReporter extends BaseReporter {
|
|
|
277
302
|
'p95',
|
|
278
303
|
'p99',
|
|
279
304
|
'error',
|
|
305
|
+
'budgetPassed',
|
|
306
|
+
'budgetViolations',
|
|
280
307
|
'timestamp',
|
|
281
308
|
];
|
|
282
309
|
|
|
@@ -302,9 +329,9 @@ export class CsvReporter extends BaseReporter {
|
|
|
302
329
|
*/
|
|
303
330
|
private generateRow(row: CsvRow): string {
|
|
304
331
|
const values = [
|
|
305
|
-
row.file
|
|
306
|
-
row.suite
|
|
307
|
-
row.task
|
|
332
|
+
row.file,
|
|
333
|
+
row.suite,
|
|
334
|
+
row.task,
|
|
308
335
|
(row.mean ?? 0).toString(),
|
|
309
336
|
(row.stdDev ?? 0).toString(),
|
|
310
337
|
(row.min ?? 0).toString(),
|
|
@@ -316,6 +343,8 @@ export class CsvReporter extends BaseReporter {
|
|
|
316
343
|
(row.p95 ?? 0).toString(),
|
|
317
344
|
(row.p99 ?? 0).toString(),
|
|
318
345
|
row.error || '',
|
|
346
|
+
row.budgetPassed !== undefined ? row.budgetPassed.toString() : '',
|
|
347
|
+
row.budgetViolations || '',
|
|
319
348
|
row.timestamp || '',
|
|
320
349
|
];
|
|
321
350
|
|
package/src/reporters/human.ts
CHANGED
|
@@ -9,54 +9,15 @@ import path from 'node:path';
|
|
|
9
9
|
|
|
10
10
|
import type {
|
|
11
11
|
BenchmarkRun,
|
|
12
|
+
BudgetSummary,
|
|
12
13
|
FileResult,
|
|
13
14
|
ProgressState,
|
|
14
15
|
SuiteResult,
|
|
15
16
|
TaskResult,
|
|
16
17
|
} from '../types/index.js';
|
|
17
18
|
|
|
18
|
-
import { BaseReporter } from '
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* ANSI color codes for terminal output
|
|
22
|
-
*/
|
|
23
|
-
const colors = {
|
|
24
|
-
bold: '\x1b[1m',
|
|
25
|
-
brightBlue: '\x1b[94m',
|
|
26
|
-
brightCyan: '\x1b[96m',
|
|
27
|
-
brightMagenta: '\x1b[95m',
|
|
28
|
-
brightRed: '\x1b[91m',
|
|
29
|
-
brightWhite: '\x1b[97m',
|
|
30
|
-
cyan: '\x1b[36m',
|
|
31
|
-
dim: '\x1b[2m',
|
|
32
|
-
gray: '\x1b[90m',
|
|
33
|
-
green: '\x1b[32m',
|
|
34
|
-
magenta: '\x1b[35m',
|
|
35
|
-
red: '\x1b[31m',
|
|
36
|
-
reset: '\x1b[0m',
|
|
37
|
-
underline: '\x1b[4m',
|
|
38
|
-
white: '\x1b[37m',
|
|
39
|
-
} as const;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* CP437-inspired ANSI art characters
|
|
43
|
-
*/
|
|
44
|
-
const ansiChars = {
|
|
45
|
-
approx: '≈',
|
|
46
|
-
// Block elements for gradients
|
|
47
|
-
block: {
|
|
48
|
-
dark: '▓',
|
|
49
|
-
full: '█',
|
|
50
|
-
light: '░',
|
|
51
|
-
medium: '▒',
|
|
52
|
-
},
|
|
53
|
-
bullet: '•',
|
|
54
|
-
// Symbols
|
|
55
|
-
checkmark: '√',
|
|
56
|
-
cross: '×',
|
|
57
|
-
plusMinus: '±',
|
|
58
|
-
smallSquare: '▪',
|
|
59
|
-
} as const;
|
|
19
|
+
import { BaseReporter } from '../services/reporter-registry.js';
|
|
20
|
+
import { ansiChars, colors } from '../utils/ansi.js';
|
|
60
21
|
|
|
61
22
|
/**
|
|
62
23
|
* Human-readable console reporter with colorized output
|
|
@@ -111,6 +72,84 @@ export class HumanReporter extends BaseReporter {
|
|
|
111
72
|
this.showProgress = options.progress ?? true;
|
|
112
73
|
}
|
|
113
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Format bytes in human-readable format
|
|
77
|
+
*/
|
|
78
|
+
private static formatBytes(this: void, bytes: number): string {
|
|
79
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
80
|
+
let size = bytes;
|
|
81
|
+
let unitIndex = 0;
|
|
82
|
+
|
|
83
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
84
|
+
size /= 1024;
|
|
85
|
+
unitIndex++;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Format file path - show relative path if within CWD, otherwise absolute
|
|
93
|
+
*/
|
|
94
|
+
private static formatPath(this: void, filePath: string): string {
|
|
95
|
+
const cwd = process.cwd();
|
|
96
|
+
const absolutePath = path.resolve(filePath);
|
|
97
|
+
|
|
98
|
+
// Check if the file is within the current working directory
|
|
99
|
+
if (absolutePath.startsWith(cwd + path.sep) || absolutePath === cwd) {
|
|
100
|
+
return path.relative(cwd, absolutePath);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return absolutePath;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Simple pluralization helper
|
|
108
|
+
*/
|
|
109
|
+
private static pluralize(this: void, str: string, count: number): string {
|
|
110
|
+
return count === 1 ? str : `${str}s`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
onBudgetResult(summary: BudgetSummary): void {
|
|
114
|
+
if (summary.total === 0 || this.quiet) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.clearProgress();
|
|
119
|
+
|
|
120
|
+
this.printLine();
|
|
121
|
+
const budgetHeader = `${this.colorize('magenta', ansiChars.block.full.repeat(2))} ${this.colorize('brightWhite', this.colorize('bold', 'Performance Budgets'))}`;
|
|
122
|
+
this.printLine(budgetHeader);
|
|
123
|
+
this.printLine();
|
|
124
|
+
|
|
125
|
+
for (const result of summary.results) {
|
|
126
|
+
const icon = result.passed ? ansiChars.checkmark : ansiChars.cross;
|
|
127
|
+
const iconColor = result.passed ? 'brightCyan' : 'brightRed';
|
|
128
|
+
|
|
129
|
+
this.printLine(
|
|
130
|
+
` ${this.colorize(iconColor, icon)} ${this.colorize('white', result.taskId)}`,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
if (!result.passed && result.violations.length > 0) {
|
|
134
|
+
for (const violation of result.violations) {
|
|
135
|
+
this.printLine(
|
|
136
|
+
` ${this.colorize('brightRed', violation.message)}`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this.printLine();
|
|
143
|
+
|
|
144
|
+
const statusText =
|
|
145
|
+
summary.failed === 0
|
|
146
|
+
? `${this.colorize('brightCyan', ansiChars.checkmark)} All ${summary.total} budget(s) passed`
|
|
147
|
+
: `${this.colorize('brightRed', ansiChars.cross)} ${summary.failed} of ${summary.total} budget(s) failed`;
|
|
148
|
+
|
|
149
|
+
this.printLine(` ${statusText}`);
|
|
150
|
+
this.printLine();
|
|
151
|
+
}
|
|
152
|
+
|
|
114
153
|
onEnd(run: BenchmarkRun): void {
|
|
115
154
|
if (this.quiet) {
|
|
116
155
|
return;
|
|
@@ -161,7 +200,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
161
200
|
);
|
|
162
201
|
}
|
|
163
202
|
this.printLine(
|
|
164
|
-
`${this.colorize('cyan', ansiChars.approx + ' Duration:')} ${this.colorize('brightWhite',
|
|
203
|
+
`${this.colorize('cyan', ansiChars.approx + ' Duration:')} ${this.colorize('brightWhite', BaseReporter.formatDuration(duration * 1000000))}`,
|
|
165
204
|
);
|
|
166
205
|
this.printLine();
|
|
167
206
|
|
|
@@ -175,7 +214,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
175
214
|
this.printLine();
|
|
176
215
|
|
|
177
216
|
for (const failure of this.failures) {
|
|
178
|
-
const displayPath =
|
|
217
|
+
const displayPath = HumanReporter.formatPath(failure.file);
|
|
179
218
|
this.printLine(
|
|
180
219
|
` ${this.colorize('dim', displayPath)} ${this.colorize('dim', '›')} ${this.colorize('white', failure.suite)} ${this.colorize('dim', '›')} ${this.colorize('brightWhite', failure.task)}`,
|
|
181
220
|
);
|
|
@@ -229,7 +268,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
229
268
|
);
|
|
230
269
|
} else {
|
|
231
270
|
this.printLine(
|
|
232
|
-
` ${this.colorize('magenta', ansiChars.checkmark)} ${totalPassed > 1 ? this.colorize('brightMagenta', 'All ') : ''}${this.colorize('bold', this.colorize('brightMagenta', `${totalPassed}`))} ${this.colorize('brightMagenta', `${
|
|
271
|
+
` ${this.colorize('magenta', ansiChars.checkmark)} ${totalPassed > 1 ? this.colorize('brightMagenta', 'All ') : ''}${this.colorize('bold', this.colorize('brightMagenta', `${totalPassed}`))} ${this.colorize('brightMagenta', `${HumanReporter.pluralize('task', totalPassed)} passed`)}`,
|
|
233
272
|
);
|
|
234
273
|
}
|
|
235
274
|
|
|
@@ -243,7 +282,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
243
282
|
return;
|
|
244
283
|
}
|
|
245
284
|
|
|
246
|
-
const displayPath =
|
|
285
|
+
const displayPath = HumanReporter.formatPath(file);
|
|
247
286
|
const fileMarker = `${colors.magenta}${ansiChars.block.dark}${ansiChars.block.dark}${colors.reset}`;
|
|
248
287
|
this.printLine(
|
|
249
288
|
`${fileMarker} ${colors.underline}${this.colorize('brightMagenta', this.colorize('bold', displayPath))}${colors.reset}`,
|
|
@@ -318,7 +357,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
318
357
|
\x1b[48;5;0m \x1b[48;5;14m \x1b[38;5;30;48;5;38m▄\x1b[38;5;14;48;5;14m▄\x1b[48;5;14m \x1b[38;5;45;48;5;14m▄\x1b[38;5;89;48;5;14m▄\x1b[38;5;89;48;5;89m▄\x1b[38;5;14;48;5;31m▄\x1b[48;5;14m \x1b[38;5;37;48;5;89m▄\x1b[48;5;198m \x1b[38;5;198;48;5;198m▄\x1b[38;5;31;48;5;14m▄\x1b[48;5;14m \x1b[48;5;0m \x1b[m \x1b[2mnode.js:\x1b[m \x1b[36m${run.environment.nodeVersion} \x1b[m
|
|
319
358
|
\x1b[48;5;0m \x1b[48;5;14m \x1b[38;5;44;48;5;31m▄\x1b[48;5;14m \x1b[38;5;126;48;5;38m▄\x1b[38;5;198;48;5;237m▄\x1b[38;5;237;48;5;37m▄\x1b[48;5;14m \x1b[38;5;14;48;5;14m▄\x1b[38;5;162;48;5;198m▄▄\x1b[38;5;53;48;5;240m▄\x1b[48;5;14m \x1b[48;5;0m \x1b[m \x1b[2mplatform:\x1b[m \x1b[36m${run.environment.platform} ${run.environment.arch} \x1b[m
|
|
320
359
|
\x1b[48;5;0m \x1b[38;5;45;48;5;14m▄\x1b[48;5;14m \x1b[38;5;14;48;5;37m▄\x1b[38;5;14;48;5;5m▄\x1b[38;5;14;48;5;44m▄\x1b[48;5;14m \x1b[38;5;45;48;5;14m▄\x1b[48;5;0m \x1b[m \x1b[2mcpu:\x1b[m \x1b[36m${run.environment.cpu.model} \x1b[2m(\x1b[m\x1b[36m${run.environment.cpu.cores} cores\x1b[2m) \x1b[m
|
|
321
|
-
\x1b[49;38;5;0m▀▀\x1b[38;5;0;48;5;6m▄\x1b[38;5;232;48;5;14m▄\x1b[38;5;38;48;5;14m▄\x1b[48;5;14m \x1b[38;5;30;48;5;14m▄\x1b[38;5;0;48;5;14m▄\x1b[38;5;0;48;5;23m▄\x1b[49;38;5;0m▀▀\x1b[m \x1b[2mmem:\x1b[m \x1b[36m${
|
|
360
|
+
\x1b[49;38;5;0m▀▀\x1b[38;5;0;48;5;6m▄\x1b[38;5;232;48;5;14m▄\x1b[38;5;38;48;5;14m▄\x1b[48;5;14m \x1b[38;5;30;48;5;14m▄\x1b[38;5;0;48;5;14m▄\x1b[38;5;0;48;5;23m▄\x1b[49;38;5;0m▀▀\x1b[m \x1b[2mmem:\x1b[m \x1b[36m${HumanReporter.formatBytes(run.environment.memory.total)} \x1b[m
|
|
322
361
|
\x1b[49m \x1b[49;38;5;0m▀\x1b[38;5;0;48;5;236m▄\x1b[38;5;0;48;5;45m▄\x1b[38;5;23;48;5;14m▄\x1b[48;5;14m \x1b[38;5;236;48;5;14m▄\x1b[38;5;0;48;5;44m▄\x1b[38;5;0;48;5;232m▄\x1b[49;38;5;0m▀\x1b[49m \x1b[m
|
|
323
362
|
\x1b[49m \x1b[49;38;5;0m▀▀\x1b[38;5;0;48;5;37m▄\x1b[38;5;0;48;5;14m▄\x1b[38;5;0;48;5;30m▄\x1b[49;38;5;0m▀▀\x1b[49m \x1b[m
|
|
324
363
|
`;
|
|
@@ -373,7 +412,7 @@ export class HumanReporter extends BaseReporter {
|
|
|
373
412
|
);
|
|
374
413
|
} else {
|
|
375
414
|
this.printLine(
|
|
376
|
-
` ${this.colorize('magenta', ansiChars.checkmark)} ${this.colorize('bold', this.colorize('brightWhite', `${passed}`))} ${this.colorize('brightWhite', `${
|
|
415
|
+
` ${this.colorize('magenta', ansiChars.checkmark)} ${this.colorize('bold', this.colorize('brightWhite', `${passed}`))} ${this.colorize('brightWhite', `${HumanReporter.pluralize('task', passed)} passed`)}`,
|
|
377
416
|
);
|
|
378
417
|
}
|
|
379
418
|
this.printLine();
|
|
@@ -454,37 +493,6 @@ export class HumanReporter extends BaseReporter {
|
|
|
454
493
|
return `${colors[color]}${text}${colors.reset}`;
|
|
455
494
|
}
|
|
456
495
|
|
|
457
|
-
/**
|
|
458
|
-
* Format bytes in human-readable format
|
|
459
|
-
*/
|
|
460
|
-
private formatBytes(bytes: number): string {
|
|
461
|
-
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
462
|
-
let size = bytes;
|
|
463
|
-
let unitIndex = 0;
|
|
464
|
-
|
|
465
|
-
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
466
|
-
size /= 1024;
|
|
467
|
-
unitIndex++;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Format file path - show relative path if within CWD, otherwise absolute
|
|
475
|
-
*/
|
|
476
|
-
private formatPath(filePath: string): string {
|
|
477
|
-
const cwd = process.cwd();
|
|
478
|
-
const absolutePath = path.resolve(filePath);
|
|
479
|
-
|
|
480
|
-
// Check if the file is within the current working directory
|
|
481
|
-
if (absolutePath.startsWith(cwd + path.sep) || absolutePath === cwd) {
|
|
482
|
-
return path.relative(cwd, absolutePath);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
return absolutePath;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
496
|
/**
|
|
489
497
|
* Format duration in human-readable format for progress display
|
|
490
498
|
*/
|
|
@@ -511,13 +519,6 @@ export class HumanReporter extends BaseReporter {
|
|
|
511
519
|
return str.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
512
520
|
}
|
|
513
521
|
|
|
514
|
-
/**
|
|
515
|
-
* Simple pluralization helper
|
|
516
|
-
*/
|
|
517
|
-
private pluralize(str: string, count: number): string {
|
|
518
|
-
return count === 1 ? str : `${str}s`;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
522
|
/**
|
|
522
523
|
* Print all task results in a suite with aligned columns
|
|
523
524
|
*/
|
|
@@ -574,9 +575,9 @@ export class HumanReporter extends BaseReporter {
|
|
|
574
575
|
};
|
|
575
576
|
}
|
|
576
577
|
|
|
577
|
-
const duration =
|
|
578
|
-
const opsPerSec =
|
|
579
|
-
const rme =
|
|
578
|
+
const duration = BaseReporter.formatDuration(result.mean); // already in nanoseconds
|
|
579
|
+
const opsPerSec = BaseReporter.formatOpsPerSecond(result.opsPerSecond);
|
|
580
|
+
const rme = BaseReporter.formatPercentage(result.marginOfError * 100);
|
|
580
581
|
|
|
581
582
|
return {
|
|
582
583
|
durationLen: this.getVisibleLength(duration),
|
package/src/reporters/json.ts
CHANGED
|
@@ -5,19 +5,14 @@
|
|
|
5
5
|
* processing, CI/CD integration, and data analysis.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
9
|
-
import { dirname } from 'node:path';
|
|
8
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { dirname, join } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
10
11
|
|
|
11
|
-
import type {
|
|
12
|
-
BenchmarkRun,
|
|
13
|
-
FileResult,
|
|
14
|
-
ProgressState,
|
|
15
|
-
SuiteResult,
|
|
16
|
-
TaskResult,
|
|
17
|
-
} from '../types/index.js';
|
|
12
|
+
import type { BenchmarkRun, TaskResult } from '../types/index.js';
|
|
18
13
|
|
|
19
14
|
import { ReporterOutputError } from '../errors/index.js';
|
|
20
|
-
import { BaseReporter } from '
|
|
15
|
+
import { BaseReporter } from '../services/reporter-registry.js';
|
|
21
16
|
|
|
22
17
|
/**
|
|
23
18
|
* JSON output structure for benchmark results
|
|
@@ -40,12 +35,30 @@ interface JsonOutput {
|
|
|
40
35
|
};
|
|
41
36
|
}
|
|
42
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Cache the package version at module load time
|
|
40
|
+
*
|
|
41
|
+
* NOTE: This relies on package.json being at the same relative path from both
|
|
42
|
+
* src/ and dist/ directories (../../package.json). If the build output
|
|
43
|
+
* structure changes, this will break.
|
|
44
|
+
*/
|
|
45
|
+
const cachedPackageVersion = (() => {
|
|
46
|
+
try {
|
|
47
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
48
|
+
const pkgPath = join(__dirname, '..', '..', 'package.json');
|
|
49
|
+
const pkgContent = readFileSync(pkgPath, 'utf8');
|
|
50
|
+
const pkg = JSON.parse(pkgContent) as { version: string };
|
|
51
|
+
return pkg.version;
|
|
52
|
+
} catch {
|
|
53
|
+
// Fallback if package.json cannot be read (shouldn't happen in normal use)
|
|
54
|
+
return 'unknown';
|
|
55
|
+
}
|
|
56
|
+
})();
|
|
57
|
+
|
|
43
58
|
/**
|
|
44
59
|
* JSON reporter for structured output
|
|
45
60
|
*/
|
|
46
61
|
export class JsonReporter extends BaseReporter {
|
|
47
|
-
private currentRun?: BenchmarkRun;
|
|
48
|
-
|
|
49
62
|
private readonly includeMetadata: boolean;
|
|
50
63
|
|
|
51
64
|
private readonly includeStatistics: boolean;
|
|
@@ -54,8 +67,6 @@ export class JsonReporter extends BaseReporter {
|
|
|
54
67
|
|
|
55
68
|
private readonly prettyPrint: boolean;
|
|
56
69
|
|
|
57
|
-
private readonly quiet: boolean;
|
|
58
|
-
|
|
59
70
|
private statistics: {
|
|
60
71
|
fastestTask?: TaskResult;
|
|
61
72
|
slowestTask?: TaskResult;
|
|
@@ -74,8 +85,6 @@ export class JsonReporter extends BaseReporter {
|
|
|
74
85
|
includeStatistics?: boolean;
|
|
75
86
|
outputPath?: string;
|
|
76
87
|
prettyPrint?: boolean;
|
|
77
|
-
quiet?: boolean;
|
|
78
|
-
verbose?: boolean;
|
|
79
88
|
} = {},
|
|
80
89
|
) {
|
|
81
90
|
super('json', options);
|
|
@@ -84,35 +93,6 @@ export class JsonReporter extends BaseReporter {
|
|
|
84
93
|
this.prettyPrint = options.prettyPrint ?? true;
|
|
85
94
|
this.includeStatistics = options.includeStatistics ?? true;
|
|
86
95
|
this.includeMetadata = options.includeMetadata ?? true;
|
|
87
|
-
this.quiet = options.quiet ?? false;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Check if statistics are included
|
|
92
|
-
*/
|
|
93
|
-
areStatisticsIncluded(): boolean {
|
|
94
|
-
return this.includeStatistics;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Get the output path (if configured)
|
|
99
|
-
*/
|
|
100
|
-
getOutputPath(): string | undefined {
|
|
101
|
-
return this.outputPath;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Check if metadata is included
|
|
106
|
-
*/
|
|
107
|
-
isMetadataIncluded(): boolean {
|
|
108
|
-
return this.includeMetadata;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Check if pretty printing is enabled
|
|
113
|
-
*/
|
|
114
|
-
isPrettyPrintEnabled(): boolean {
|
|
115
|
-
return this.prettyPrint;
|
|
116
96
|
}
|
|
117
97
|
|
|
118
98
|
async onEnd(run: BenchmarkRun): Promise<void> {
|
|
@@ -131,41 +111,16 @@ export class JsonReporter extends BaseReporter {
|
|
|
131
111
|
console.error('JSON Reporter Error:', error.message);
|
|
132
112
|
}
|
|
133
113
|
|
|
134
|
-
|
|
135
|
-
// No-op for JSON reporter
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
onFileStart(_file: string): void {
|
|
139
|
-
// No-op for JSON reporter
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
onProgress(_state: ProgressState): void {
|
|
143
|
-
// No-op for JSON reporter - we don't output progress in JSON format
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
onStart(run: BenchmarkRun): void {
|
|
147
|
-
this.currentRun = run;
|
|
114
|
+
onStart(_run: BenchmarkRun): void {
|
|
148
115
|
this.resetStatistics();
|
|
149
116
|
}
|
|
150
117
|
|
|
151
|
-
onSuiteEnd(_result: SuiteResult): void {
|
|
152
|
-
// No-op for JSON reporter
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
onSuiteStart(_suite: string): void {
|
|
156
|
-
// No-op for JSON reporter
|
|
157
|
-
}
|
|
158
|
-
|
|
159
118
|
onTaskResult(result: TaskResult): void {
|
|
160
119
|
if (!result.error) {
|
|
161
120
|
this.updateStatistics(result);
|
|
162
121
|
}
|
|
163
122
|
}
|
|
164
123
|
|
|
165
|
-
onTaskStart(_task: string): void {
|
|
166
|
-
// No-op for JSON reporter
|
|
167
|
-
}
|
|
168
|
-
|
|
169
124
|
/**
|
|
170
125
|
* Build the complete JSON output structure
|
|
171
126
|
*/
|
|
@@ -174,7 +129,7 @@ export class JsonReporter extends BaseReporter {
|
|
|
174
129
|
meta: {
|
|
175
130
|
format: 'modestbench-json',
|
|
176
131
|
timestamp: new Date().toISOString(),
|
|
177
|
-
version:
|
|
132
|
+
version: cachedPackageVersion,
|
|
178
133
|
},
|
|
179
134
|
run: this.includeMetadata ? run : this.sanitizeRun(run),
|
|
180
135
|
};
|