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.
Files changed (484) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +162 -57
  3. package/dist/bootstrap.cjs +10 -10
  4. package/dist/bootstrap.cjs.map +1 -1
  5. package/dist/bootstrap.d.cts.map +1 -1
  6. package/dist/bootstrap.d.ts.map +1 -1
  7. package/dist/bootstrap.js +5 -5
  8. package/dist/bootstrap.js.map +1 -1
  9. package/dist/cli/commands/analyze.cjs +60 -0
  10. package/dist/cli/commands/analyze.cjs.map +1 -0
  11. package/dist/cli/commands/analyze.d.cts +35 -0
  12. package/dist/cli/commands/analyze.d.cts.map +1 -0
  13. package/dist/cli/commands/analyze.d.ts +35 -0
  14. package/dist/cli/commands/analyze.d.ts.map +1 -0
  15. package/dist/cli/commands/analyze.js +56 -0
  16. package/dist/cli/commands/analyze.js.map +1 -0
  17. package/dist/cli/commands/baseline.cjs +404 -0
  18. package/dist/cli/commands/baseline.cjs.map +1 -0
  19. package/dist/cli/commands/baseline.d.cts +72 -0
  20. package/dist/cli/commands/baseline.d.cts.map +1 -0
  21. package/dist/cli/commands/baseline.d.ts +72 -0
  22. package/dist/cli/commands/baseline.d.ts.map +1 -0
  23. package/dist/cli/commands/baseline.js +396 -0
  24. package/dist/cli/commands/baseline.js.map +1 -0
  25. package/dist/cli/commands/history.cjs +108 -266
  26. package/dist/cli/commands/history.cjs.map +1 -1
  27. package/dist/cli/commands/history.d.cts +75 -12
  28. package/dist/cli/commands/history.d.cts.map +1 -1
  29. package/dist/cli/commands/history.d.ts +75 -12
  30. package/dist/cli/commands/history.d.ts.map +1 -1
  31. package/dist/cli/commands/history.js +105 -268
  32. package/dist/cli/commands/history.js.map +1 -1
  33. package/dist/cli/commands/init.cjs +88 -155
  34. package/dist/cli/commands/init.cjs.map +1 -1
  35. package/dist/cli/commands/init.d.cts +4 -4
  36. package/dist/cli/commands/init.d.cts.map +1 -1
  37. package/dist/cli/commands/init.d.ts +4 -4
  38. package/dist/cli/commands/init.d.ts.map +1 -1
  39. package/dist/cli/commands/init.js +88 -155
  40. package/dist/cli/commands/init.js.map +1 -1
  41. package/dist/cli/commands/run.cjs +143 -112
  42. package/dist/cli/commands/run.cjs.map +1 -1
  43. package/dist/cli/commands/run.d.cts +17 -3
  44. package/dist/cli/commands/run.d.cts.map +1 -1
  45. package/dist/cli/commands/run.d.ts +17 -3
  46. package/dist/cli/commands/run.d.ts.map +1 -1
  47. package/dist/cli/commands/run.js +142 -78
  48. package/dist/cli/commands/run.js.map +1 -1
  49. package/dist/cli/index.cjs +671 -266
  50. package/dist/cli/index.cjs.map +1 -1
  51. package/dist/cli/index.d.cts +4 -16
  52. package/dist/cli/index.d.cts.map +1 -1
  53. package/dist/cli/index.d.ts +4 -16
  54. package/dist/cli/index.d.ts.map +1 -1
  55. package/dist/cli/index.js +664 -259
  56. package/dist/cli/index.js.map +1 -1
  57. package/dist/config/budget-schema.cjs +172 -0
  58. package/dist/config/budget-schema.cjs.map +1 -0
  59. package/dist/config/budget-schema.d.cts +59 -0
  60. package/dist/config/budget-schema.d.cts.map +1 -0
  61. package/dist/config/budget-schema.d.ts +59 -0
  62. package/dist/config/budget-schema.d.ts.map +1 -0
  63. package/dist/config/budget-schema.js +166 -0
  64. package/dist/config/budget-schema.js.map +1 -0
  65. package/dist/config/schema.cjs +182 -2
  66. package/dist/config/schema.cjs.map +1 -1
  67. package/dist/config/schema.d.cts +122 -3
  68. package/dist/config/schema.d.cts.map +1 -1
  69. package/dist/config/schema.d.ts +122 -3
  70. package/dist/config/schema.d.ts.map +1 -1
  71. package/dist/config/schema.js +180 -1
  72. package/dist/config/schema.js.map +1 -1
  73. package/dist/constants.cjs +45 -2
  74. package/dist/constants.cjs.map +1 -1
  75. package/dist/constants.d.cts +41 -0
  76. package/dist/constants.d.cts.map +1 -1
  77. package/dist/constants.d.ts +41 -0
  78. package/dist/constants.d.ts.map +1 -1
  79. package/dist/constants.js +44 -1
  80. package/dist/constants.js.map +1 -1
  81. package/dist/core/engine.cjs +104 -15
  82. package/dist/core/engine.cjs.map +1 -1
  83. package/dist/core/engine.d.cts +7 -4
  84. package/dist/core/engine.d.cts.map +1 -1
  85. package/dist/core/engine.d.ts +7 -4
  86. package/dist/core/engine.d.ts.map +1 -1
  87. package/dist/core/engine.js +105 -16
  88. package/dist/core/engine.js.map +1 -1
  89. package/dist/core/output-path-resolver.cjs +41 -0
  90. package/dist/core/output-path-resolver.cjs.map +1 -0
  91. package/dist/core/output-path-resolver.d.cts +10 -0
  92. package/dist/core/output-path-resolver.d.cts.map +1 -0
  93. package/dist/core/output-path-resolver.d.ts +10 -0
  94. package/dist/core/output-path-resolver.d.ts.map +1 -0
  95. package/dist/core/output-path-resolver.js +37 -0
  96. package/dist/core/output-path-resolver.js.map +1 -0
  97. package/dist/errors/base.cjs +12 -3
  98. package/dist/errors/base.cjs.map +1 -1
  99. package/dist/errors/base.d.cts +7 -0
  100. package/dist/errors/base.d.cts.map +1 -1
  101. package/dist/errors/base.d.ts +7 -0
  102. package/dist/errors/base.d.ts.map +1 -1
  103. package/dist/errors/base.js +10 -2
  104. package/dist/errors/base.js.map +1 -1
  105. package/dist/errors/budget.cjs +37 -0
  106. package/dist/errors/budget.cjs.map +1 -0
  107. package/dist/errors/budget.d.cts +31 -0
  108. package/dist/errors/budget.d.cts.map +1 -0
  109. package/dist/errors/budget.d.ts +31 -0
  110. package/dist/errors/budget.d.ts.map +1 -0
  111. package/dist/errors/budget.js +33 -0
  112. package/dist/errors/budget.js.map +1 -0
  113. package/dist/errors/index.cjs +4 -1
  114. package/dist/errors/index.cjs.map +1 -1
  115. package/dist/errors/index.d.cts +1 -0
  116. package/dist/errors/index.d.cts.map +1 -1
  117. package/dist/errors/index.d.ts +1 -0
  118. package/dist/errors/index.d.ts.map +1 -1
  119. package/dist/errors/index.js +2 -0
  120. package/dist/errors/index.js.map +1 -1
  121. package/dist/formatters/history/base.cjs +9 -0
  122. package/dist/formatters/history/base.cjs.map +1 -0
  123. package/dist/formatters/history/base.d.cts +26 -0
  124. package/dist/formatters/history/base.d.cts.map +1 -0
  125. package/dist/formatters/history/base.d.ts +26 -0
  126. package/dist/formatters/history/base.d.ts.map +1 -0
  127. package/dist/formatters/history/base.js +8 -0
  128. package/dist/formatters/history/base.js.map +1 -0
  129. package/dist/formatters/history/compare.cjs +127 -0
  130. package/dist/formatters/history/compare.cjs.map +1 -0
  131. package/dist/formatters/history/compare.d.cts +21 -0
  132. package/dist/formatters/history/compare.d.cts.map +1 -0
  133. package/dist/formatters/history/compare.d.ts +21 -0
  134. package/dist/formatters/history/compare.d.ts.map +1 -0
  135. package/dist/formatters/history/compare.js +123 -0
  136. package/dist/formatters/history/compare.js.map +1 -0
  137. package/dist/formatters/history/list.cjs +74 -0
  138. package/dist/formatters/history/list.cjs.map +1 -0
  139. package/dist/formatters/history/list.d.cts +25 -0
  140. package/dist/formatters/history/list.d.cts.map +1 -0
  141. package/dist/formatters/history/list.d.ts +25 -0
  142. package/dist/formatters/history/list.d.ts.map +1 -0
  143. package/dist/formatters/history/list.js +70 -0
  144. package/dist/formatters/history/list.js.map +1 -0
  145. package/dist/formatters/history/show.cjs +98 -0
  146. package/dist/formatters/history/show.cjs.map +1 -0
  147. package/dist/formatters/history/show.d.cts +21 -0
  148. package/dist/formatters/history/show.d.cts.map +1 -0
  149. package/dist/formatters/history/show.d.ts +21 -0
  150. package/dist/formatters/history/show.d.ts.map +1 -0
  151. package/dist/formatters/history/show.js +94 -0
  152. package/dist/formatters/history/show.js.map +1 -0
  153. package/dist/formatters/history/trends.cjs +194 -0
  154. package/dist/formatters/history/trends.cjs.map +1 -0
  155. package/dist/formatters/history/trends.d.cts +22 -0
  156. package/dist/formatters/history/trends.d.cts.map +1 -0
  157. package/dist/formatters/history/trends.d.ts +22 -0
  158. package/dist/formatters/history/trends.d.ts.map +1 -0
  159. package/dist/formatters/history/trends.js +190 -0
  160. package/dist/formatters/history/trends.js.map +1 -0
  161. package/dist/formatters/history/visualization.cjs +79 -0
  162. package/dist/formatters/history/visualization.cjs.map +1 -0
  163. package/dist/formatters/history/visualization.d.cts +24 -0
  164. package/dist/formatters/history/visualization.d.cts.map +1 -0
  165. package/dist/formatters/history/visualization.d.ts +24 -0
  166. package/dist/formatters/history/visualization.d.ts.map +1 -0
  167. package/dist/formatters/history/visualization.js +74 -0
  168. package/dist/formatters/history/visualization.js.map +1 -0
  169. package/dist/index.cjs +27 -17
  170. package/dist/index.cjs.map +1 -1
  171. package/dist/index.d.cts +10 -5
  172. package/dist/index.d.cts.map +1 -1
  173. package/dist/index.d.ts +10 -5
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +14 -9
  176. package/dist/index.js.map +1 -1
  177. package/dist/reporters/csv.cjs +39 -19
  178. package/dist/reporters/csv.cjs.map +1 -1
  179. package/dist/reporters/csv.d.cts +4 -7
  180. package/dist/reporters/csv.d.cts.map +1 -1
  181. package/dist/reporters/csv.d.ts +4 -7
  182. package/dist/reporters/csv.d.ts.map +1 -1
  183. package/dist/reporters/csv.js +38 -18
  184. package/dist/reporters/csv.js.map +1 -1
  185. package/dist/reporters/human.cjs +87 -99
  186. package/dist/reporters/human.cjs.map +1 -1
  187. package/dist/reporters/human.d.cts +15 -14
  188. package/dist/reporters/human.d.cts.map +1 -1
  189. package/dist/reporters/human.d.ts +15 -14
  190. package/dist/reporters/human.d.ts.map +1 -1
  191. package/dist/reporters/human.js +68 -80
  192. package/dist/reporters/human.js.map +1 -1
  193. package/dist/reporters/json.cjs +25 -50
  194. package/dist/reporters/json.cjs.map +1 -1
  195. package/dist/reporters/json.d.cts +3 -29
  196. package/dist/reporters/json.d.cts.map +1 -1
  197. package/dist/reporters/json.d.ts +3 -29
  198. package/dist/reporters/json.d.ts.map +1 -1
  199. package/dist/reporters/json.js +26 -51
  200. package/dist/reporters/json.js.map +1 -1
  201. package/dist/reporters/profile-human.cjs +149 -0
  202. package/dist/reporters/profile-human.cjs.map +1 -0
  203. package/dist/reporters/profile-human.d.cts +44 -0
  204. package/dist/reporters/profile-human.d.cts.map +1 -0
  205. package/dist/reporters/profile-human.d.ts +44 -0
  206. package/dist/reporters/profile-human.d.ts.map +1 -0
  207. package/dist/reporters/profile-human.js +142 -0
  208. package/dist/reporters/profile-human.js.map +1 -0
  209. package/dist/reporters/simple.cjs +66 -46
  210. package/dist/reporters/simple.cjs.map +1 -1
  211. package/dist/reporters/simple.d.cts +15 -15
  212. package/dist/reporters/simple.d.cts.map +1 -1
  213. package/dist/reporters/simple.d.ts +15 -15
  214. package/dist/reporters/simple.d.ts.map +1 -1
  215. package/dist/reporters/simple.js +65 -45
  216. package/dist/reporters/simple.js.map +1 -1
  217. package/dist/schema/modestbench-config.schema.json +153 -0
  218. package/dist/services/baseline-storage.cjs +151 -0
  219. package/dist/services/baseline-storage.cjs.map +1 -0
  220. package/dist/services/baseline-storage.d.cts +55 -0
  221. package/dist/services/baseline-storage.d.cts.map +1 -0
  222. package/dist/services/baseline-storage.d.ts +55 -0
  223. package/dist/services/baseline-storage.d.ts.map +1 -0
  224. package/dist/services/baseline-storage.js +147 -0
  225. package/dist/services/baseline-storage.js.map +1 -0
  226. package/dist/services/budget-evaluator.cjs +146 -0
  227. package/dist/services/budget-evaluator.cjs.map +1 -0
  228. package/dist/services/budget-evaluator.d.cts +29 -0
  229. package/dist/services/budget-evaluator.d.cts.map +1 -0
  230. package/dist/services/budget-evaluator.d.ts +29 -0
  231. package/dist/services/budget-evaluator.d.ts.map +1 -0
  232. package/dist/services/budget-evaluator.js +142 -0
  233. package/dist/services/budget-evaluator.js.map +1 -0
  234. package/dist/{config/manager.cjs → services/config-manager.cjs} +25 -11
  235. package/dist/services/config-manager.cjs.map +1 -0
  236. package/dist/{config/manager.d.cts → services/config-manager.d.cts} +7 -2
  237. package/dist/services/config-manager.d.cts.map +1 -0
  238. package/dist/{config/manager.d.ts → services/config-manager.d.ts} +7 -2
  239. package/dist/services/config-manager.d.ts.map +1 -0
  240. package/dist/{config/manager.js → services/config-manager.js} +25 -11
  241. package/dist/services/config-manager.js.map +1 -0
  242. package/dist/{core/loader.cjs → services/file-loader.cjs} +5 -8
  243. package/dist/services/file-loader.cjs.map +1 -0
  244. package/dist/{core/loader.d.cts → services/file-loader.d.cts} +1 -1
  245. package/dist/services/file-loader.d.cts.map +1 -0
  246. package/dist/{core/loader.d.ts → services/file-loader.d.ts} +1 -1
  247. package/dist/services/file-loader.d.ts.map +1 -0
  248. package/dist/{core/loader.js → services/file-loader.js} +5 -8
  249. package/dist/services/file-loader.js.map +1 -0
  250. package/dist/services/history/comparison.cjs +124 -0
  251. package/dist/services/history/comparison.cjs.map +1 -0
  252. package/dist/services/history/comparison.d.cts +18 -0
  253. package/dist/services/history/comparison.d.cts.map +1 -0
  254. package/dist/services/history/comparison.d.ts +18 -0
  255. package/dist/services/history/comparison.d.ts.map +1 -0
  256. package/dist/services/history/comparison.js +120 -0
  257. package/dist/services/history/comparison.js.map +1 -0
  258. package/dist/services/history/models.cjs +9 -0
  259. package/dist/services/history/models.cjs.map +1 -0
  260. package/dist/services/history/models.d.cts +139 -0
  261. package/dist/services/history/models.d.cts.map +1 -0
  262. package/dist/services/history/models.d.ts +139 -0
  263. package/dist/services/history/models.d.ts.map +1 -0
  264. package/dist/services/history/models.js +8 -0
  265. package/dist/services/history/models.js.map +1 -0
  266. package/dist/services/history/query.cjs +97 -0
  267. package/dist/services/history/query.cjs.map +1 -0
  268. package/dist/services/history/query.d.cts +38 -0
  269. package/dist/services/history/query.d.cts.map +1 -0
  270. package/dist/services/history/query.d.ts +38 -0
  271. package/dist/services/history/query.d.ts.map +1 -0
  272. package/dist/services/history/query.js +92 -0
  273. package/dist/services/history/query.js.map +1 -0
  274. package/dist/services/history/trend-analysis.cjs +187 -0
  275. package/dist/services/history/trend-analysis.cjs.map +1 -0
  276. package/dist/services/history/trend-analysis.d.cts +34 -0
  277. package/dist/services/history/trend-analysis.d.cts.map +1 -0
  278. package/dist/services/history/trend-analysis.d.ts +34 -0
  279. package/dist/services/history/trend-analysis.d.ts.map +1 -0
  280. package/dist/services/history/trend-analysis.js +179 -0
  281. package/dist/services/history/trend-analysis.js.map +1 -0
  282. package/dist/{storage/history.cjs → services/history-storage.cjs} +1 -1
  283. package/dist/services/history-storage.cjs.map +1 -0
  284. package/dist/{storage/history.d.cts → services/history-storage.d.cts} +1 -1
  285. package/dist/services/history-storage.d.cts.map +1 -0
  286. package/dist/{storage/history.d.ts → services/history-storage.d.ts} +1 -1
  287. package/dist/services/history-storage.d.ts.map +1 -0
  288. package/dist/{storage/history.js → services/history-storage.js} +1 -1
  289. package/dist/services/history-storage.js.map +1 -0
  290. package/dist/services/profiler/profile-filter.cjs +113 -0
  291. package/dist/services/profiler/profile-filter.cjs.map +1 -0
  292. package/dist/services/profiler/profile-filter.d.cts +20 -0
  293. package/dist/services/profiler/profile-filter.d.cts.map +1 -0
  294. package/dist/services/profiler/profile-filter.d.ts +20 -0
  295. package/dist/services/profiler/profile-filter.d.ts.map +1 -0
  296. package/dist/services/profiler/profile-filter.js +109 -0
  297. package/dist/services/profiler/profile-filter.js.map +1 -0
  298. package/dist/services/profiler/profile-parser.cjs +139 -0
  299. package/dist/services/profiler/profile-parser.cjs.map +1 -0
  300. package/dist/services/profiler/profile-parser.d.cts +18 -0
  301. package/dist/services/profiler/profile-parser.d.cts.map +1 -0
  302. package/dist/services/profiler/profile-parser.d.ts +18 -0
  303. package/dist/services/profiler/profile-parser.d.ts.map +1 -0
  304. package/dist/services/profiler/profile-parser.js +132 -0
  305. package/dist/services/profiler/profile-parser.js.map +1 -0
  306. package/dist/services/profiler/profile-runner.cjs +90 -0
  307. package/dist/services/profiler/profile-runner.cjs.map +1 -0
  308. package/dist/services/profiler/profile-runner.d.cts +29 -0
  309. package/dist/services/profiler/profile-runner.d.cts.map +1 -0
  310. package/dist/services/profiler/profile-runner.d.ts +29 -0
  311. package/dist/services/profiler/profile-runner.d.ts.map +1 -0
  312. package/dist/services/profiler/profile-runner.js +86 -0
  313. package/dist/services/profiler/profile-runner.js.map +1 -0
  314. package/dist/{progress/manager.cjs → services/progress-manager.cjs} +1 -1
  315. package/dist/services/progress-manager.cjs.map +1 -0
  316. package/dist/{progress/manager.d.cts → services/progress-manager.d.cts} +1 -1
  317. package/dist/services/progress-manager.d.cts.map +1 -0
  318. package/dist/{progress/manager.d.ts → services/progress-manager.d.ts} +1 -1
  319. package/dist/services/progress-manager.d.ts.map +1 -0
  320. package/dist/{progress/manager.js → services/progress-manager.js} +1 -1
  321. package/dist/services/progress-manager.js.map +1 -0
  322. package/dist/{reporters/registry.cjs → services/reporter-registry.cjs} +19 -25
  323. package/dist/services/reporter-registry.cjs.map +1 -0
  324. package/dist/{reporters/registry.d.cts → services/reporter-registry.d.cts} +19 -41
  325. package/dist/services/reporter-registry.d.cts.map +1 -0
  326. package/dist/{reporters/registry.d.ts → services/reporter-registry.d.ts} +19 -41
  327. package/dist/services/reporter-registry.d.ts.map +1 -0
  328. package/dist/{reporters/registry.js → services/reporter-registry.js} +19 -25
  329. package/dist/services/reporter-registry.js.map +1 -0
  330. package/dist/types/budgets.cjs +8 -0
  331. package/dist/types/budgets.cjs.map +1 -0
  332. package/dist/types/budgets.d.cts +149 -0
  333. package/dist/types/budgets.d.cts.map +1 -0
  334. package/dist/types/budgets.d.ts +149 -0
  335. package/dist/types/budgets.d.ts.map +1 -0
  336. package/dist/types/budgets.js +7 -0
  337. package/dist/types/budgets.js.map +1 -0
  338. package/dist/types/cli.cjs +2 -11
  339. package/dist/types/cli.cjs.map +1 -1
  340. package/dist/types/cli.d.cts +3 -224
  341. package/dist/types/cli.d.cts.map +1 -1
  342. package/dist/types/cli.d.ts +3 -224
  343. package/dist/types/cli.d.ts.map +1 -1
  344. package/dist/types/cli.js +2 -11
  345. package/dist/types/cli.js.map +1 -1
  346. package/dist/types/core.cjs +6 -1
  347. package/dist/types/core.cjs.map +1 -1
  348. package/dist/types/core.d.cts +13 -2
  349. package/dist/types/core.d.cts.map +1 -1
  350. package/dist/types/core.d.ts +13 -2
  351. package/dist/types/core.d.ts.map +1 -1
  352. package/dist/types/core.js +2 -1
  353. package/dist/types/core.js.map +1 -1
  354. package/dist/types/index.cjs +5 -0
  355. package/dist/types/index.cjs.map +1 -1
  356. package/dist/types/index.d.cts +2 -0
  357. package/dist/types/index.d.cts.map +1 -1
  358. package/dist/types/index.d.ts +2 -0
  359. package/dist/types/index.d.ts.map +1 -1
  360. package/dist/types/index.js +2 -0
  361. package/dist/types/index.js.map +1 -1
  362. package/dist/types/interfaces.d.cts +15 -8
  363. package/dist/types/interfaces.d.cts.map +1 -1
  364. package/dist/types/interfaces.d.ts +15 -8
  365. package/dist/types/interfaces.d.ts.map +1 -1
  366. package/dist/types/profiler.cjs +11 -0
  367. package/dist/types/profiler.cjs.map +1 -0
  368. package/dist/types/profiler.d.cts +100 -0
  369. package/dist/types/profiler.d.cts.map +1 -0
  370. package/dist/types/profiler.d.ts +100 -0
  371. package/dist/types/profiler.d.ts.map +1 -0
  372. package/dist/types/profiler.js +10 -0
  373. package/dist/types/profiler.js.map +1 -0
  374. package/dist/types/utility.cjs.map +1 -1
  375. package/dist/types/utility.d.cts +0 -8
  376. package/dist/types/utility.d.cts.map +1 -1
  377. package/dist/types/utility.d.ts +0 -8
  378. package/dist/types/utility.d.ts.map +1 -1
  379. package/dist/types/utility.js.map +1 -1
  380. package/dist/utils/ansi.cjs +61 -0
  381. package/dist/utils/ansi.cjs.map +1 -0
  382. package/dist/utils/ansi.d.cts +53 -0
  383. package/dist/utils/ansi.d.cts.map +1 -0
  384. package/dist/utils/ansi.d.ts +53 -0
  385. package/dist/utils/ansi.d.ts.map +1 -0
  386. package/dist/utils/ansi.js +57 -0
  387. package/dist/utils/ansi.js.map +1 -0
  388. package/dist/utils/identifiers.cjs +32 -0
  389. package/dist/utils/identifiers.cjs.map +1 -0
  390. package/dist/utils/identifiers.d.cts +32 -0
  391. package/dist/utils/identifiers.d.cts.map +1 -0
  392. package/dist/utils/identifiers.d.ts +32 -0
  393. package/dist/utils/identifiers.d.ts.map +1 -0
  394. package/dist/utils/identifiers.js +27 -0
  395. package/dist/utils/identifiers.js.map +1 -0
  396. package/dist/utils/package.cjs +40 -0
  397. package/dist/utils/package.cjs.map +1 -0
  398. package/dist/utils/package.d.cts +15 -0
  399. package/dist/utils/package.d.cts.map +1 -0
  400. package/dist/utils/package.d.ts +15 -0
  401. package/dist/utils/package.d.ts.map +1 -0
  402. package/dist/utils/package.js +33 -0
  403. package/dist/utils/package.js.map +1 -0
  404. package/dist/utils/type-guards.cjs +48 -0
  405. package/dist/utils/type-guards.cjs.map +1 -0
  406. package/dist/utils/type-guards.d.cts +22 -0
  407. package/dist/utils/type-guards.d.cts.map +1 -0
  408. package/dist/utils/type-guards.d.ts +22 -0
  409. package/dist/utils/type-guards.d.ts.map +1 -0
  410. package/dist/utils/type-guards.js +43 -0
  411. package/dist/utils/type-guards.js.map +1 -0
  412. package/package.json +14 -13
  413. package/src/bootstrap.ts +5 -5
  414. package/src/cli/commands/analyze.ts +101 -0
  415. package/src/cli/commands/baseline.ts +577 -0
  416. package/src/cli/commands/history.ts +194 -342
  417. package/src/cli/commands/init.ts +105 -183
  418. package/src/cli/commands/run.ts +186 -88
  419. package/src/cli/index.ts +731 -234
  420. package/src/config/budget-schema.ts +189 -0
  421. package/src/config/schema.ts +260 -1
  422. package/src/constants.ts +53 -1
  423. package/src/core/engine.ts +153 -14
  424. package/src/core/output-path-resolver.ts +46 -0
  425. package/src/errors/base.ts +11 -2
  426. package/src/errors/budget.ts +38 -0
  427. package/src/errors/index.ts +3 -0
  428. package/src/formatters/history/base.ts +28 -0
  429. package/src/formatters/history/compare.ts +186 -0
  430. package/src/formatters/history/list.ts +101 -0
  431. package/src/formatters/history/show.ts +155 -0
  432. package/src/formatters/history/trends.ts +281 -0
  433. package/src/formatters/history/visualization.ts +93 -0
  434. package/src/index.ts +17 -12
  435. package/src/reporters/csv.ts +55 -26
  436. package/src/reporters/human.ts +90 -89
  437. package/src/reporters/json.ts +27 -72
  438. package/src/reporters/profile-human.ts +204 -0
  439. package/src/reporters/simple.ts +85 -54
  440. package/src/services/baseline-storage.ts +199 -0
  441. package/src/services/budget-evaluator.ts +182 -0
  442. package/src/{config/manager.ts → services/config-manager.ts} +24 -9
  443. package/src/{core/loader.ts → services/file-loader.ts} +4 -7
  444. package/src/services/history/comparison.ts +130 -0
  445. package/src/services/history/models.ts +148 -0
  446. package/src/services/history/query.ts +116 -0
  447. package/src/services/history/trend-analysis.ts +238 -0
  448. package/src/services/profiler/profile-filter.ts +143 -0
  449. package/src/services/profiler/profile-parser.ts +194 -0
  450. package/src/services/profiler/profile-runner.ts +121 -0
  451. package/src/{reporters/registry.ts → services/reporter-registry.ts} +46 -81
  452. package/src/types/budgets.ts +180 -0
  453. package/src/types/cli.ts +5 -235
  454. package/src/types/core.ts +50 -10
  455. package/src/types/index.ts +5 -0
  456. package/src/types/interfaces.ts +16 -6
  457. package/src/types/profiler.ts +132 -0
  458. package/src/types/utility.ts +0 -10
  459. package/src/utils/ansi.ts +59 -0
  460. package/src/utils/identifiers.ts +58 -0
  461. package/src/utils/package.ts +35 -0
  462. package/src/utils/type-guards.ts +51 -0
  463. package/dist/config/manager.cjs.map +0 -1
  464. package/dist/config/manager.d.cts.map +0 -1
  465. package/dist/config/manager.d.ts.map +0 -1
  466. package/dist/config/manager.js.map +0 -1
  467. package/dist/core/loader.cjs.map +0 -1
  468. package/dist/core/loader.d.cts.map +0 -1
  469. package/dist/core/loader.d.ts.map +0 -1
  470. package/dist/core/loader.js.map +0 -1
  471. package/dist/progress/manager.cjs.map +0 -1
  472. package/dist/progress/manager.d.cts.map +0 -1
  473. package/dist/progress/manager.d.ts.map +0 -1
  474. package/dist/progress/manager.js.map +0 -1
  475. package/dist/reporters/registry.cjs.map +0 -1
  476. package/dist/reporters/registry.d.cts.map +0 -1
  477. package/dist/reporters/registry.d.ts.map +0 -1
  478. package/dist/reporters/registry.js.map +0 -1
  479. package/dist/storage/history.cjs.map +0 -1
  480. package/dist/storage/history.d.cts.map +0 -1
  481. package/dist/storage/history.d.ts.map +0 -1
  482. package/dist/storage/history.js.map +0 -1
  483. /package/src/{storage/history.ts → services/history-storage.ts} +0 -0
  484. /package/src/{progress/manager.ts → services/progress-manager.ts} +0 -0
@@ -5,72 +5,94 @@
5
5
  * comparing, and cleaning historical data.
6
6
  */
7
7
 
8
- import type { HistoryQuery, RetentionPolicy } from '../../types/index.js';
8
+ import type {
9
+ HistoryQuery,
10
+ HistoryStorage,
11
+ RetentionPolicy,
12
+ } from '../../types/index.js';
9
13
  import type { CliContext } from '../index.js';
10
14
 
11
- import { InvalidDateFormatError } from '../../errors/index.js';
15
+ import { HistoryCompareFormatter } from '../../formatters/history/compare.js';
16
+ import { HistoryListFormatter } from '../../formatters/history/list.js';
17
+ import { HistoryShowFormatter } from '../../formatters/history/show.js';
18
+ import { HistoryTrendsFormatter } from '../../formatters/history/trends.js';
19
+ import { ComparisonService } from '../../services/history/comparison.js';
20
+ import {
21
+ HistoryQueryService,
22
+ parseDate,
23
+ } from '../../services/history/query.js';
24
+ import { TrendAnalysisService } from '../../services/history/trend-analysis.js';
12
25
 
13
26
  /**
14
- * History command options interface
27
+ * Base options shared by all history subcommands
15
28
  */
16
- interface HistoryOptions {
17
- args?: string[] | undefined; // Additional arguments after subcommand
29
+ interface BaseHistoryOptions {
30
+ cwd?: string;
31
+ quiet?: boolean | undefined;
32
+ verbose?: boolean | undefined;
33
+ }
34
+
35
+ /**
36
+ * Options for history clean command
37
+ */
38
+ interface HistoryCleanOptions extends BaseHistoryOptions {
18
39
  confirm?: boolean | undefined;
19
- cwd: string;
20
- format?: 'csv' | 'human' | 'json' | undefined;
21
- limit?: number | undefined;
22
40
  maxAge?: number | undefined;
23
41
  maxRuns?: number | undefined;
24
42
  maxSize?: number | undefined;
25
- outputDir?: string | undefined;
43
+ }
44
+
45
+ /**
46
+ * Options for history compare command
47
+ */
48
+ interface HistoryCompareOptions extends BaseHistoryOptions {
49
+ format?: 'human' | 'json' | undefined;
50
+ runId1: string;
51
+ runId2: string;
52
+ }
53
+
54
+ /**
55
+ * Options for history export command
56
+ */
57
+ interface HistoryExportOptions extends BaseHistoryOptions {
58
+ format?: 'csv' | 'json' | undefined;
59
+ outputPath: string;
60
+ since?: string | undefined;
61
+ until?: string | undefined;
62
+ }
63
+
64
+ /**
65
+ * Options for history list command
66
+ */
67
+ interface HistoryListOptions extends BaseHistoryOptions {
68
+ format?: 'csv' | 'human' | 'json' | undefined;
69
+ limit?: number | undefined;
26
70
  pattern?: string | undefined;
27
- quiet?: boolean | undefined;
28
71
  since?: string | undefined;
29
- subcommand: 'clean' | 'compare' | 'export' | 'list' | 'show' | 'trends';
30
72
  tags?: string[] | undefined;
31
73
  until?: string | undefined;
32
- verbose?: boolean | undefined;
33
74
  }
34
75
 
35
76
  /**
36
- * Handle history command
77
+ * Options for history show command
37
78
  */
38
- export const handleHistoryCommand = async (
39
- context: CliContext,
40
- options: HistoryOptions,
41
- ): Promise<number> => {
42
- try {
43
- // Get the subcommand
44
- const subcommand = options.subcommand;
45
-
46
- switch (subcommand) {
47
- case 'clean':
48
- return await handleCleanCommand(context, options);
49
- case 'compare':
50
- return await handleCompareCommand(context, options);
51
- case 'export':
52
- return await handleExportCommand(context, options);
53
- case 'list':
54
- return await handleListCommand(context, options);
55
- case 'show':
56
- return await handleShowCommand(context, options);
57
- case 'trends':
58
- return await handleTrendsCommand(context, options);
59
- default:
60
- console.error(`Unknown history subcommand: ${subcommand || '(none)'}`);
61
- console.error(
62
- 'Available subcommands: list, show, compare, trends, clean, export',
63
- );
64
- return 2; // Config error
65
- }
66
- } catch (error) {
67
- console.error(
68
- 'History command failed:',
69
- error instanceof Error ? error.message : String(error),
70
- );
71
- return 2; // Configuration/runtime errors
72
- }
73
- };
79
+ interface HistoryShowOptions extends BaseHistoryOptions {
80
+ format?: 'csv' | 'human' | 'json' | undefined;
81
+ runId: string;
82
+ }
83
+
84
+ /**
85
+ * Options for history trends command
86
+ */
87
+ interface HistoryTrendsOptions extends BaseHistoryOptions {
88
+ all?: boolean | undefined;
89
+ format?: 'human' | 'json' | undefined;
90
+ limit?: number | undefined;
91
+ pattern?: string | undefined;
92
+ since?: string | undefined;
93
+ tags?: string[] | undefined;
94
+ until?: string | undefined;
95
+ }
74
96
 
75
97
  /**
76
98
  * Format bytes in human-readable format
@@ -88,12 +110,38 @@ const formatBytes = (bytes: number): string => {
88
110
  return `${size.toFixed(1)} ${units[unitIndex]}`;
89
111
  };
90
112
 
113
+ /**
114
+ * Resolve a partial run ID to a full ID by checking prefix match
115
+ *
116
+ * Supports Git-style partial ID matching (e.g., "k3m" matches "k3m9x2p")
117
+ */
118
+ const resolveRunId = async (
119
+ storage: HistoryStorage,
120
+ partialId: string,
121
+ ): Promise<null | string> => {
122
+ // First try exact match
123
+ const exactRun = await storage.loadRun(partialId);
124
+ if (exactRun) {
125
+ return partialId;
126
+ }
127
+
128
+ // Query all runs to find a prefix match
129
+ const allRuns = await storage.queryRuns({});
130
+
131
+ const prefixMatch = allRuns.find((run) => run.id.startsWith(partialId));
132
+ if (prefixMatch) {
133
+ return prefixMatch.id;
134
+ }
135
+
136
+ return null;
137
+ };
138
+
91
139
  /**
92
140
  * Handle the clean subcommand
93
141
  */
94
- const handleCleanCommand = async (
142
+ export const handleCleanCommand = async (
95
143
  context: CliContext,
96
- options: HistoryOptions,
144
+ options: HistoryCleanOptions,
97
145
  ): Promise<number> => {
98
146
  try {
99
147
  // Build retention policy from arguments
@@ -160,69 +208,38 @@ const handleCleanCommand = async (
160
208
  /**
161
209
  * Handle the compare subcommand
162
210
  */
163
- const handleCompareCommand = async (
211
+ export const handleCompareCommand = async (
164
212
  context: CliContext,
165
- options: HistoryOptions,
213
+ options: HistoryCompareOptions,
166
214
  ): Promise<number> => {
167
215
  try {
168
- // For compare command, IDs come from args after the subcommand
169
- const id1 = options.args?.[0];
170
- const id2 = options.args?.[1];
171
-
172
- if (!id1 || !id2) {
173
- console.error('Two run IDs are required for compare command');
174
- console.error('Usage: modestbench history compare <run-id1> <run-id2>');
175
- return 2;
176
- }
177
-
178
216
  const [run1, run2] = await Promise.all([
179
- context.historyStorage.loadRun(id1),
180
- context.historyStorage.loadRun(id2),
217
+ context.historyStorage.loadRun(options.runId1),
218
+ context.historyStorage.loadRun(options.runId2),
181
219
  ]);
182
220
 
183
221
  if (!run1) {
184
- console.error(`Run not found: ${id1}`);
222
+ console.error(`Run not found: ${options.runId1}`);
185
223
  return 1;
186
224
  }
187
225
 
188
226
  if (!run2) {
189
- console.error(`Run not found: ${id2}`);
227
+ console.error(`Run not found: ${options.runId2}`);
190
228
  return 1;
191
229
  }
192
230
 
193
- if (options.format === 'json') {
194
- const comparison = {
195
- run1: { id: run1.id, summary: run1.summary },
196
- run2: { id: run2.id, summary: run2.summary },
197
- // TODO: Add detailed comparison logic
198
- };
199
- console.log(JSON.stringify(comparison, null, 2));
200
- } else {
201
- // Human format comparison
202
- console.log(`Comparing runs:`);
203
- console.log(` Run 1: ${run1.id} (${run1.startTime.toLocaleString()})`);
204
- console.log(` Run 2: ${run2.id} (${run2.startTime.toLocaleString()})`);
205
- console.log();
206
-
207
- console.log('Summary comparison:');
208
- console.log(
209
- ` Files: ${run1.summary.totalFiles} vs ${run2.summary.totalFiles}`,
210
- );
211
- console.log(
212
- ` Tasks: ${run1.summary.totalTasks} vs ${run2.summary.totalTasks}`,
213
- );
214
- console.log(
215
- ` Passed: ${run1.summary.passedTasks} vs ${run2.summary.passedTasks}`,
216
- );
217
- console.log(
218
- ` Failed: ${run1.summary.failedTasks} vs ${run2.summary.failedTasks}`,
219
- );
231
+ // Compare using service
232
+ const comparisonService = new ComparisonService();
233
+ const result = comparisonService.compareRuns(run1, run2);
220
234
 
221
- // TODO: Add detailed performance comparison
222
- console.log();
223
- console.log('Note: Detailed performance comparison not yet implemented.');
224
- }
235
+ // Format output
236
+ const formatter = new HistoryCompareFormatter();
237
+ const output =
238
+ options.format === 'json'
239
+ ? formatter.formatJson(result)
240
+ : formatter.formatHuman(result);
225
241
 
242
+ console.log(output);
226
243
  return 0;
227
244
  } catch (error) {
228
245
  console.error(
@@ -236,9 +253,9 @@ const handleCompareCommand = async (
236
253
  /**
237
254
  * Handle the export subcommand
238
255
  */
239
- const handleExportCommand = async (
256
+ export const handleExportCommand = async (
240
257
  context: CliContext,
241
- options: HistoryOptions,
258
+ options: HistoryExportOptions,
242
259
  ): Promise<number> => {
243
260
  try {
244
261
  const format = options.format || 'json';
@@ -249,21 +266,13 @@ const handleExportCommand = async (
249
266
  ...(options.until && { until: parseDate(options.until) }),
250
267
  } as Partial<HistoryQuery>;
251
268
 
252
- const exportData = await context.historyStorage.export(
253
- format as 'csv' | 'json',
254
- query,
255
- );
269
+ const exportData = await context.historyStorage.export(format, query);
256
270
 
257
- if (options.outputDir) {
258
- // Write to file
259
- const fs = await import('node:fs/promises');
260
- await fs.writeFile(options.outputDir, exportData, 'utf8');
261
- if (!options.quiet) {
262
- console.log(`Exported history to ${options.outputDir}`);
263
- }
264
- } else {
265
- // Write to stdout
266
- console.log(exportData);
271
+ // Write to file
272
+ const fs = await import('node:fs/promises');
273
+ await fs.writeFile(options.outputPath, exportData, 'utf8');
274
+ if (!options.quiet) {
275
+ console.log(`Exported history to ${options.outputPath}`);
267
276
  }
268
277
 
269
278
  return 0;
@@ -279,110 +288,39 @@ const handleExportCommand = async (
279
288
  /**
280
289
  * Handle the list subcommand
281
290
  */
282
- const handleListCommand = async (
291
+ export const handleListCommand = async (
283
292
  context: CliContext,
284
- options: HistoryOptions,
293
+ options: HistoryListOptions,
285
294
  ): Promise<number> => {
286
295
  try {
287
- // Build query from command line arguments
288
- let parsedSince: Date | undefined;
289
- let parsedUntil: Date | undefined;
290
-
291
- if (options.since) {
292
- try {
293
- parsedSince = parseDate(options.since);
294
- } catch (error) {
295
- console.error(
296
- 'Invalid since date:',
297
- error instanceof Error ? error.message : String(error),
298
- );
299
- return 2; // Invalid date format
300
- }
301
- }
302
-
303
- if (options.until) {
304
- try {
305
- parsedUntil = parseDate(options.until);
306
- } catch (error) {
307
- console.error(
308
- 'Invalid until date:',
309
- error instanceof Error ? error.message : String(error),
310
- );
311
- return 2; // Invalid date format
312
- }
313
- }
314
-
315
- const query = {
316
- ...(parsedSince && { since: parsedSince }),
317
- ...(parsedUntil && { until: parsedUntil }),
318
- ...(options.pattern && { pattern: options.pattern }),
319
- ...(options.tags && options.tags.length > 0 && { tags: options.tags }),
320
- ...(options.limit && { limit: options.limit }),
321
- } as Partial<HistoryQuery>;
322
-
323
- // Query historical runs
324
- const runs = await context.historyStorage.queryRuns(query);
296
+ // Query runs using service
297
+ const queryService = new HistoryQueryService(context.historyStorage);
298
+ const runs = await queryService.queryWithDateParsing(options);
299
+
300
+ // Transform to result format
301
+ const result = {
302
+ runs: runs.map((run) => ({
303
+ duration: run.duration,
304
+ id: run.id,
305
+ startTime: run.startTime,
306
+ summary: run.summary,
307
+ })),
308
+ totalCount: runs.length,
309
+ };
310
+
311
+ // Format output
312
+ const formatter = new HistoryListFormatter();
313
+ let output: string;
325
314
 
326
- // Display results based on format
327
315
  if (options.format === 'json') {
328
- if (runs.length === 0) {
329
- console.log('[]'); // Empty JSON array for no data
330
- } else {
331
- console.log(
332
- JSON.stringify(
333
- runs.map((run) => ({
334
- duration: run.duration,
335
- failed: run.summary.failedTasks,
336
- files: run.summary.totalFiles,
337
- id: run.id,
338
- passed: run.summary.passedTasks,
339
- startTime: run.startTime,
340
- tasks: run.summary.totalTasks,
341
- })),
342
- null,
343
- 2,
344
- ),
345
- );
346
- }
316
+ output = formatter.formatJson(result);
347
317
  } else if (options.format === 'csv') {
348
- console.log('id,startTime,duration,files,tasks,passed,failed');
349
- if (runs.length > 0) {
350
- for (const run of runs) {
351
- console.log(
352
- `${run.id},${run.startTime.toISOString()},${run.duration},${run.summary.totalFiles},${run.summary.totalTasks},${run.summary.passedTasks},${run.summary.failedTasks}`,
353
- );
354
- }
355
- }
356
- // For CSV, no additional message needed - header is sufficient
318
+ output = formatter.formatCsv(result);
357
319
  } else {
358
- // Human format
359
- if (runs.length === 0) {
360
- if (!options.quiet) {
361
- console.log('No historical data found matching criteria.');
362
- }
363
- } else {
364
- console.log('Recent benchmark runs:');
365
- console.log();
366
-
367
- for (const run of runs) {
368
- const dateStr = run.startTime.toLocaleString();
369
- const durationStr = `${(run.duration / 1000).toFixed(1)}s`;
370
- const statusStr =
371
- run.summary.failedTasks > 0
372
- ? `${run.summary.passedTasks} passed, ${run.summary.failedTasks} failed`
373
- : `${run.summary.passedTasks} passed`;
374
-
375
- console.log(
376
- ` ${run.id.substring(0, 8)} - ${dateStr} (${durationStr})`,
377
- );
378
- console.log(
379
- ` ${run.summary.totalFiles} files, ${run.summary.totalTasks} tasks: ${statusStr}`,
380
- );
381
- console.log();
382
- }
383
- }
320
+ output = formatter.formatHuman(result);
384
321
  }
385
322
 
323
+ console.log(output);
386
324
  return 0;
387
325
  } catch (error) {
388
326
  console.error(
@@ -396,68 +334,34 @@ const handleListCommand = async (
396
334
  /**
397
335
  * Handle the show subcommand
398
336
  */
399
- const handleShowCommand = async (
337
+ export const handleShowCommand = async (
400
338
  context: CliContext,
401
- options: HistoryOptions,
339
+ options: HistoryShowOptions,
402
340
  ): Promise<number> => {
403
341
  try {
404
- // For show command, ID comes from the args after the subcommand
405
- const runId = options.args?.[0];
342
+ // Resolve partial ID to full ID
343
+ const fullRunId = await resolveRunId(context.historyStorage, options.runId);
406
344
 
407
- if (!runId) {
408
- console.error('Run ID is required for show command');
409
- console.error('Usage: modestbench history show <run-id>');
410
- return 2;
345
+ if (!fullRunId) {
346
+ console.error(`Run not found: ${options.runId}`);
347
+ return 1;
411
348
  }
412
349
 
413
- const run = await context.historyStorage.loadRun(runId);
350
+ const run = await context.historyStorage.loadRun(fullRunId);
414
351
 
415
352
  if (!run) {
416
- console.error(`Run not found: ${runId}`);
353
+ console.error(`Run not found: ${options.runId}`);
417
354
  return 1;
418
355
  }
419
356
 
420
- if (options.format === 'json') {
421
- console.log(JSON.stringify(run, null, 2));
422
- } else {
423
- // Human format
424
- console.log(`Benchmark Run: ${run.id}`);
425
- console.log(`Date: ${run.startTime.toLocaleString()}`);
426
- console.log(`Duration: ${(run.duration / 1000).toFixed(1)}s`);
427
- console.log(
428
- `Environment: Node.js ${run.environment.nodeVersion} on ${run.environment.platform}`,
429
- );
430
-
431
- if (run.git) {
432
- console.log(`Git: ${run.git.branch}@${run.git.commit.substring(0, 8)}`);
433
- }
434
-
435
- console.log();
436
- console.log('Summary:');
437
- console.log(` Files: ${run.summary.totalFiles}`);
438
- console.log(` Suites: ${run.summary.totalSuites}`);
439
- console.log(` Tasks: ${run.summary.totalTasks}`);
440
- console.log(` Passed: ${run.summary.passedTasks}`);
441
- console.log(` Failed: ${run.summary.failedTasks}`);
442
-
443
- // TODO: Show detailed file/suite/task results
444
- console.log();
445
- console.log('Detailed results:');
446
- for (const file of run.files) {
447
- console.log(` 📁 ${file.filePath}`);
448
- for (const suite of file.suites) {
449
- console.log(` 📊 ${suite.name}`);
450
- for (const task of suite.tasks) {
451
- const status = task.error ? '❌' : '✅';
452
- const timing = task.error
453
- ? 'failed'
454
- : `${(task.mean / 1000000).toFixed(2)}ms`;
455
- console.log(` ${status} ${task.name} - ${timing}`);
456
- }
457
- }
458
- }
459
- }
357
+ // Format output
358
+ const formatter = new HistoryShowFormatter();
359
+ const output =
360
+ options.format === 'json'
361
+ ? formatter.formatJson(run)
362
+ : formatter.formatHuman(run);
460
363
 
364
+ console.log(output);
461
365
  return 0;
462
366
  } catch (error) {
463
367
  console.error(
@@ -471,101 +375,49 @@ const handleShowCommand = async (
471
375
  /**
472
376
  * Handle the trends subcommand
473
377
  */
474
- const handleTrendsCommand = async (
378
+ export const handleTrendsCommand = async (
475
379
  context: CliContext,
476
- options: HistoryOptions,
380
+ options: HistoryTrendsOptions,
477
381
  ): Promise<number> => {
478
382
  try {
479
- // Build query from command line arguments (same as list command)
480
- let parsedSince: Date | undefined;
481
- let parsedUntil: Date | undefined;
482
-
483
- if (options.since) {
484
- try {
485
- parsedSince = parseDate(options.since);
486
- } catch (error) {
487
- console.error(
488
- 'Invalid since date:',
489
- error instanceof Error ? error.message : String(error),
490
- );
491
- return 2; // Invalid date format
492
- }
493
- }
494
-
495
- if (options.until) {
496
- try {
497
- parsedUntil = parseDate(options.until);
498
- } catch (error) {
499
- console.error(
500
- 'Invalid until date:',
501
- error instanceof Error ? error.message : String(error),
502
- );
503
- return 2; // Invalid date format
504
- }
505
- }
506
-
507
- // Get pattern from args or explicit pattern option
508
- const pattern = options.args?.[0] || options.pattern;
509
-
510
- const query = {
511
- ...(parsedSince && { since: parsedSince }),
512
- ...(parsedUntil && { until: parsedUntil }),
513
- ...(pattern && { pattern }),
514
- ...(options.tags && options.tags.length > 0 && { tags: options.tags }),
515
- ...(options.limit && { limit: options.limit }),
516
- } as Partial<HistoryQuery>;
517
-
518
- // Query historical runs
519
- const runs = await context.historyStorage.queryRuns(query);
383
+ // Query runs using service
384
+ const queryService = new HistoryQueryService(context.historyStorage);
385
+ const runs = await queryService.queryWithDateParsing({
386
+ limit: options.all ? undefined : options.limit,
387
+ pattern: options.pattern,
388
+ since: options.since,
389
+ tags: options.tags,
390
+ until: options.until,
391
+ });
520
392
 
521
393
  if (runs.length === 0) {
522
394
  if (!options.quiet) {
523
395
  console.log('No historical data found matching criteria');
524
396
  }
525
- return 0; // Success - no data is not an error
397
+ return 0;
526
398
  }
527
399
 
528
- if (options.format === 'json') {
529
- // TODO: Generate trends data in JSON format
530
- const trendsData = {
531
- runs: runs.length,
532
- timespan: {
533
- end: runs[0]?.startTime,
534
- start: runs[runs.length - 1]?.startTime,
535
- },
536
- // TODO: Add actual trend calculations
537
- };
538
- console.log(JSON.stringify(trendsData, null, 2));
539
- } else {
540
- // Human format trends
541
- if (!options.quiet) {
542
- console.log(`Performance trends for ${runs.length} runs:`);
543
- console.log(
544
- `Time range: ${runs[runs.length - 1]?.startTime} to ${runs[0]?.startTime}`,
545
- );
546
- // TODO: Add trend analysis and visualization
547
- console.log('(Trend analysis not yet implemented)');
548
- }
400
+ // Analyze trends using service
401
+ const analysisService = new TrendAnalysisService();
402
+ const result = analysisService.analyzeTrends(runs);
403
+
404
+ // Format output
405
+ const formatter = new HistoryTrendsFormatter();
406
+ const output =
407
+ options.format === 'json'
408
+ ? formatter.formatJson(result)
409
+ : formatter.formatHuman(result);
410
+
411
+ if (!options.quiet || options.format !== 'human') {
412
+ console.log(output);
549
413
  }
550
414
 
551
- return 0; // Success
415
+ return 0;
552
416
  } catch (error) {
553
- console.error('Error showing trends:', error);
554
- return 3; // Runtime error
555
- }
556
- };
557
-
558
- /**
559
- * Parse date string (ISO 8601 or relative)
560
- */
561
- const parseDate = (dateStr: string): Date => {
562
- // Try parsing as ISO 8601 first
563
- const isoDate = new Date(dateStr);
564
- if (!isNaN(isoDate.getTime())) {
565
- return isoDate;
417
+ console.error(
418
+ 'Failed to show trends:',
419
+ error instanceof Error ? error.message : String(error),
420
+ );
421
+ return 5;
566
422
  }
567
-
568
- // TODO: Parse relative dates like "1 week ago", "3 days ago", etc.
569
- // For now, throw error for invalid dates
570
- throw new InvalidDateFormatError(`Invalid date format: "${dateStr}"`);
571
423
  };