modestbench 0.2.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 (332) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +131 -34
  3. package/dist/cli/commands/analyze.cjs +60 -0
  4. package/dist/cli/commands/analyze.cjs.map +1 -0
  5. package/dist/cli/commands/analyze.d.cts +35 -0
  6. package/dist/cli/commands/analyze.d.cts.map +1 -0
  7. package/dist/cli/commands/analyze.d.ts +35 -0
  8. package/dist/cli/commands/analyze.d.ts.map +1 -0
  9. package/dist/cli/commands/analyze.js +56 -0
  10. package/dist/cli/commands/analyze.js.map +1 -0
  11. package/dist/cli/commands/baseline.cjs +404 -0
  12. package/dist/cli/commands/baseline.cjs.map +1 -0
  13. package/dist/cli/commands/baseline.d.cts +72 -0
  14. package/dist/cli/commands/baseline.d.cts.map +1 -0
  15. package/dist/cli/commands/baseline.d.ts +72 -0
  16. package/dist/cli/commands/baseline.d.ts.map +1 -0
  17. package/dist/cli/commands/baseline.js +396 -0
  18. package/dist/cli/commands/baseline.js.map +1 -0
  19. package/dist/cli/commands/history.d.cts +1 -1
  20. package/dist/cli/commands/history.d.cts.map +1 -1
  21. package/dist/cli/commands/history.d.ts +1 -1
  22. package/dist/cli/commands/history.d.ts.map +1 -1
  23. package/dist/cli/commands/init.cjs +88 -155
  24. package/dist/cli/commands/init.cjs.map +1 -1
  25. package/dist/cli/commands/init.d.cts +4 -4
  26. package/dist/cli/commands/init.d.cts.map +1 -1
  27. package/dist/cli/commands/init.d.ts +4 -4
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +88 -155
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/run.cjs +132 -114
  32. package/dist/cli/commands/run.cjs.map +1 -1
  33. package/dist/cli/commands/run.d.cts +16 -3
  34. package/dist/cli/commands/run.d.cts.map +1 -1
  35. package/dist/cli/commands/run.d.ts +16 -3
  36. package/dist/cli/commands/run.d.ts.map +1 -1
  37. package/dist/cli/commands/run.js +131 -80
  38. package/dist/cli/commands/run.js.map +1 -1
  39. package/dist/cli/index.cjs +583 -394
  40. package/dist/cli/index.cjs.map +1 -1
  41. package/dist/cli/index.d.cts +4 -16
  42. package/dist/cli/index.d.cts.map +1 -1
  43. package/dist/cli/index.d.ts +4 -16
  44. package/dist/cli/index.d.ts.map +1 -1
  45. package/dist/cli/index.js +575 -386
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/config/budget-schema.cjs +172 -0
  48. package/dist/config/budget-schema.cjs.map +1 -0
  49. package/dist/config/budget-schema.d.cts +59 -0
  50. package/dist/config/budget-schema.d.cts.map +1 -0
  51. package/dist/config/budget-schema.d.ts +59 -0
  52. package/dist/config/budget-schema.d.ts.map +1 -0
  53. package/dist/config/budget-schema.js +166 -0
  54. package/dist/config/budget-schema.js.map +1 -0
  55. package/dist/config/schema.cjs +182 -2
  56. package/dist/config/schema.cjs.map +1 -1
  57. package/dist/config/schema.d.cts +122 -3
  58. package/dist/config/schema.d.cts.map +1 -1
  59. package/dist/config/schema.d.ts +122 -3
  60. package/dist/config/schema.d.ts.map +1 -1
  61. package/dist/config/schema.js +180 -1
  62. package/dist/config/schema.js.map +1 -1
  63. package/dist/constants.cjs +45 -2
  64. package/dist/constants.cjs.map +1 -1
  65. package/dist/constants.d.cts +41 -0
  66. package/dist/constants.d.cts.map +1 -1
  67. package/dist/constants.d.ts +41 -0
  68. package/dist/constants.d.ts.map +1 -1
  69. package/dist/constants.js +44 -1
  70. package/dist/constants.js.map +1 -1
  71. package/dist/core/engine.cjs +103 -21
  72. package/dist/core/engine.cjs.map +1 -1
  73. package/dist/core/engine.d.cts +7 -7
  74. package/dist/core/engine.d.cts.map +1 -1
  75. package/dist/core/engine.d.ts +7 -7
  76. package/dist/core/engine.d.ts.map +1 -1
  77. package/dist/core/engine.js +104 -22
  78. package/dist/core/engine.js.map +1 -1
  79. package/dist/core/output-path-resolver.cjs +8 -1
  80. package/dist/core/output-path-resolver.cjs.map +1 -1
  81. package/dist/core/output-path-resolver.d.cts.map +1 -1
  82. package/dist/core/output-path-resolver.d.ts.map +1 -1
  83. package/dist/core/output-path-resolver.js +9 -2
  84. package/dist/core/output-path-resolver.js.map +1 -1
  85. package/dist/errors/base.cjs +12 -3
  86. package/dist/errors/base.cjs.map +1 -1
  87. package/dist/errors/base.d.cts +7 -0
  88. package/dist/errors/base.d.cts.map +1 -1
  89. package/dist/errors/base.d.ts +7 -0
  90. package/dist/errors/base.d.ts.map +1 -1
  91. package/dist/errors/base.js +10 -2
  92. package/dist/errors/base.js.map +1 -1
  93. package/dist/errors/budget.cjs +37 -0
  94. package/dist/errors/budget.cjs.map +1 -0
  95. package/dist/errors/budget.d.cts +31 -0
  96. package/dist/errors/budget.d.cts.map +1 -0
  97. package/dist/errors/budget.d.ts +31 -0
  98. package/dist/errors/budget.d.ts.map +1 -0
  99. package/dist/errors/budget.js +33 -0
  100. package/dist/errors/budget.js.map +1 -0
  101. package/dist/errors/index.cjs +4 -1
  102. package/dist/errors/index.cjs.map +1 -1
  103. package/dist/errors/index.d.cts +1 -0
  104. package/dist/errors/index.d.cts.map +1 -1
  105. package/dist/errors/index.d.ts +1 -0
  106. package/dist/errors/index.d.ts.map +1 -1
  107. package/dist/errors/index.js +2 -0
  108. package/dist/errors/index.js.map +1 -1
  109. package/dist/index.cjs +13 -1
  110. package/dist/index.cjs.map +1 -1
  111. package/dist/index.d.cts +5 -0
  112. package/dist/index.d.cts.map +1 -1
  113. package/dist/index.d.ts +5 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +7 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/reporters/csv.cjs +37 -17
  118. package/dist/reporters/csv.cjs.map +1 -1
  119. package/dist/reporters/csv.d.cts +3 -6
  120. package/dist/reporters/csv.d.cts.map +1 -1
  121. package/dist/reporters/csv.d.ts +3 -6
  122. package/dist/reporters/csv.d.ts.map +1 -1
  123. package/dist/reporters/csv.js +37 -17
  124. package/dist/reporters/csv.js.map +1 -1
  125. package/dist/reporters/human.cjs +66 -40
  126. package/dist/reporters/human.cjs.map +1 -1
  127. package/dist/reporters/human.d.cts +14 -13
  128. package/dist/reporters/human.d.cts.map +1 -1
  129. package/dist/reporters/human.d.ts +14 -13
  130. package/dist/reporters/human.d.ts.map +1 -1
  131. package/dist/reporters/human.js +66 -40
  132. package/dist/reporters/human.js.map +1 -1
  133. package/dist/reporters/json.cjs +23 -48
  134. package/dist/reporters/json.cjs.map +1 -1
  135. package/dist/reporters/json.d.cts +2 -28
  136. package/dist/reporters/json.d.cts.map +1 -1
  137. package/dist/reporters/json.d.ts +2 -28
  138. package/dist/reporters/json.d.ts.map +1 -1
  139. package/dist/reporters/json.js +25 -50
  140. package/dist/reporters/json.js.map +1 -1
  141. package/dist/reporters/profile-human.cjs +149 -0
  142. package/dist/reporters/profile-human.cjs.map +1 -0
  143. package/dist/reporters/profile-human.d.cts +44 -0
  144. package/dist/reporters/profile-human.d.cts.map +1 -0
  145. package/dist/reporters/profile-human.d.ts +44 -0
  146. package/dist/reporters/profile-human.d.ts.map +1 -0
  147. package/dist/reporters/profile-human.js +142 -0
  148. package/dist/reporters/profile-human.js.map +1 -0
  149. package/dist/reporters/simple.cjs +64 -44
  150. package/dist/reporters/simple.cjs.map +1 -1
  151. package/dist/reporters/simple.d.cts +14 -14
  152. package/dist/reporters/simple.d.cts.map +1 -1
  153. package/dist/reporters/simple.d.ts +14 -14
  154. package/dist/reporters/simple.d.ts.map +1 -1
  155. package/dist/reporters/simple.js +64 -44
  156. package/dist/reporters/simple.js.map +1 -1
  157. package/dist/schema/modestbench-config.schema.json +153 -0
  158. package/dist/services/baseline-storage.cjs +151 -0
  159. package/dist/services/baseline-storage.cjs.map +1 -0
  160. package/dist/services/baseline-storage.d.cts +55 -0
  161. package/dist/services/baseline-storage.d.cts.map +1 -0
  162. package/dist/services/baseline-storage.d.ts +55 -0
  163. package/dist/services/baseline-storage.d.ts.map +1 -0
  164. package/dist/services/baseline-storage.js +147 -0
  165. package/dist/services/baseline-storage.js.map +1 -0
  166. package/dist/services/budget-evaluator.cjs +146 -0
  167. package/dist/services/budget-evaluator.cjs.map +1 -0
  168. package/dist/services/budget-evaluator.d.cts +29 -0
  169. package/dist/services/budget-evaluator.d.cts.map +1 -0
  170. package/dist/services/budget-evaluator.d.ts +29 -0
  171. package/dist/services/budget-evaluator.d.ts.map +1 -0
  172. package/dist/services/budget-evaluator.js +142 -0
  173. package/dist/services/budget-evaluator.js.map +1 -0
  174. package/dist/services/config-manager.cjs +23 -9
  175. package/dist/services/config-manager.cjs.map +1 -1
  176. package/dist/services/config-manager.d.cts +6 -1
  177. package/dist/services/config-manager.d.cts.map +1 -1
  178. package/dist/services/config-manager.d.ts +6 -1
  179. package/dist/services/config-manager.d.ts.map +1 -1
  180. package/dist/services/config-manager.js +23 -9
  181. package/dist/services/config-manager.js.map +1 -1
  182. package/dist/services/file-loader.cjs +3 -6
  183. package/dist/services/file-loader.cjs.map +1 -1
  184. package/dist/services/file-loader.d.cts.map +1 -1
  185. package/dist/services/file-loader.d.ts.map +1 -1
  186. package/dist/services/file-loader.js +3 -6
  187. package/dist/services/file-loader.js.map +1 -1
  188. package/dist/services/profiler/profile-filter.cjs +113 -0
  189. package/dist/services/profiler/profile-filter.cjs.map +1 -0
  190. package/dist/services/profiler/profile-filter.d.cts +20 -0
  191. package/dist/services/profiler/profile-filter.d.cts.map +1 -0
  192. package/dist/services/profiler/profile-filter.d.ts +20 -0
  193. package/dist/services/profiler/profile-filter.d.ts.map +1 -0
  194. package/dist/services/profiler/profile-filter.js +109 -0
  195. package/dist/services/profiler/profile-filter.js.map +1 -0
  196. package/dist/services/profiler/profile-parser.cjs +139 -0
  197. package/dist/services/profiler/profile-parser.cjs.map +1 -0
  198. package/dist/services/profiler/profile-parser.d.cts +18 -0
  199. package/dist/services/profiler/profile-parser.d.cts.map +1 -0
  200. package/dist/services/profiler/profile-parser.d.ts +18 -0
  201. package/dist/services/profiler/profile-parser.d.ts.map +1 -0
  202. package/dist/services/profiler/profile-parser.js +132 -0
  203. package/dist/services/profiler/profile-parser.js.map +1 -0
  204. package/dist/services/profiler/profile-runner.cjs +90 -0
  205. package/dist/services/profiler/profile-runner.cjs.map +1 -0
  206. package/dist/services/profiler/profile-runner.d.cts +29 -0
  207. package/dist/services/profiler/profile-runner.d.cts.map +1 -0
  208. package/dist/services/profiler/profile-runner.d.ts +29 -0
  209. package/dist/services/profiler/profile-runner.d.ts.map +1 -0
  210. package/dist/services/profiler/profile-runner.js +86 -0
  211. package/dist/services/profiler/profile-runner.js.map +1 -0
  212. package/dist/services/reporter-registry.cjs +18 -24
  213. package/dist/services/reporter-registry.cjs.map +1 -1
  214. package/dist/services/reporter-registry.d.cts +18 -40
  215. package/dist/services/reporter-registry.d.cts.map +1 -1
  216. package/dist/services/reporter-registry.d.ts +18 -40
  217. package/dist/services/reporter-registry.d.ts.map +1 -1
  218. package/dist/services/reporter-registry.js +18 -24
  219. package/dist/services/reporter-registry.js.map +1 -1
  220. package/dist/types/budgets.cjs +8 -0
  221. package/dist/types/budgets.cjs.map +1 -0
  222. package/dist/types/budgets.d.cts +149 -0
  223. package/dist/types/budgets.d.cts.map +1 -0
  224. package/dist/types/budgets.d.ts +149 -0
  225. package/dist/types/budgets.d.ts.map +1 -0
  226. package/dist/types/budgets.js +7 -0
  227. package/dist/types/budgets.js.map +1 -0
  228. package/dist/types/cli.cjs +2 -11
  229. package/dist/types/cli.cjs.map +1 -1
  230. package/dist/types/cli.d.cts +3 -227
  231. package/dist/types/cli.d.cts.map +1 -1
  232. package/dist/types/cli.d.ts +3 -227
  233. package/dist/types/cli.d.ts.map +1 -1
  234. package/dist/types/cli.js +2 -11
  235. package/dist/types/cli.js.map +1 -1
  236. package/dist/types/core.cjs +6 -1
  237. package/dist/types/core.cjs.map +1 -1
  238. package/dist/types/core.d.cts +13 -2
  239. package/dist/types/core.d.cts.map +1 -1
  240. package/dist/types/core.d.ts +13 -2
  241. package/dist/types/core.d.ts.map +1 -1
  242. package/dist/types/core.js +2 -1
  243. package/dist/types/core.js.map +1 -1
  244. package/dist/types/index.cjs +5 -0
  245. package/dist/types/index.cjs.map +1 -1
  246. package/dist/types/index.d.cts +2 -0
  247. package/dist/types/index.d.cts.map +1 -1
  248. package/dist/types/index.d.ts +2 -0
  249. package/dist/types/index.d.ts.map +1 -1
  250. package/dist/types/index.js +2 -0
  251. package/dist/types/index.js.map +1 -1
  252. package/dist/types/interfaces.d.cts +15 -8
  253. package/dist/types/interfaces.d.cts.map +1 -1
  254. package/dist/types/interfaces.d.ts +15 -8
  255. package/dist/types/interfaces.d.ts.map +1 -1
  256. package/dist/types/profiler.cjs +11 -0
  257. package/dist/types/profiler.cjs.map +1 -0
  258. package/dist/types/profiler.d.cts +100 -0
  259. package/dist/types/profiler.d.cts.map +1 -0
  260. package/dist/types/profiler.d.ts +100 -0
  261. package/dist/types/profiler.d.ts.map +1 -0
  262. package/dist/types/profiler.js +10 -0
  263. package/dist/types/profiler.js.map +1 -0
  264. package/dist/types/utility.cjs.map +1 -1
  265. package/dist/types/utility.d.cts +0 -8
  266. package/dist/types/utility.d.cts.map +1 -1
  267. package/dist/types/utility.d.ts +0 -8
  268. package/dist/types/utility.d.ts.map +1 -1
  269. package/dist/types/utility.js.map +1 -1
  270. package/dist/utils/identifiers.cjs +32 -0
  271. package/dist/utils/identifiers.cjs.map +1 -0
  272. package/dist/utils/identifiers.d.cts +32 -0
  273. package/dist/utils/identifiers.d.cts.map +1 -0
  274. package/dist/utils/identifiers.d.ts +32 -0
  275. package/dist/utils/identifiers.d.ts.map +1 -0
  276. package/dist/utils/identifiers.js +27 -0
  277. package/dist/utils/identifiers.js.map +1 -0
  278. package/dist/utils/package.cjs +40 -0
  279. package/dist/utils/package.cjs.map +1 -0
  280. package/dist/utils/package.d.cts +15 -0
  281. package/dist/utils/package.d.cts.map +1 -0
  282. package/dist/utils/package.d.ts +15 -0
  283. package/dist/utils/package.d.ts.map +1 -0
  284. package/dist/utils/package.js +33 -0
  285. package/dist/utils/package.js.map +1 -0
  286. package/dist/utils/type-guards.cjs +48 -0
  287. package/dist/utils/type-guards.cjs.map +1 -0
  288. package/dist/utils/type-guards.d.cts +22 -0
  289. package/dist/utils/type-guards.d.cts.map +1 -0
  290. package/dist/utils/type-guards.d.ts +22 -0
  291. package/dist/utils/type-guards.d.ts.map +1 -0
  292. package/dist/utils/type-guards.js +43 -0
  293. package/dist/utils/type-guards.js.map +1 -0
  294. package/package.json +10 -10
  295. package/src/cli/commands/analyze.ts +101 -0
  296. package/src/cli/commands/baseline.ts +577 -0
  297. package/src/cli/commands/history.ts +1 -1
  298. package/src/cli/commands/init.ts +105 -183
  299. package/src/cli/commands/run.ts +167 -98
  300. package/src/cli/index.ts +425 -183
  301. package/src/config/budget-schema.ts +189 -0
  302. package/src/config/schema.ts +260 -1
  303. package/src/constants.ts +53 -1
  304. package/src/core/engine.ts +151 -20
  305. package/src/core/output-path-resolver.ts +10 -2
  306. package/src/errors/base.ts +11 -2
  307. package/src/errors/budget.ts +38 -0
  308. package/src/errors/index.ts +3 -0
  309. package/src/index.ts +9 -0
  310. package/src/reporters/csv.ts +54 -25
  311. package/src/reporters/human.ts +88 -47
  312. package/src/reporters/json.ts +26 -71
  313. package/src/reporters/profile-human.ts +204 -0
  314. package/src/reporters/simple.ts +84 -53
  315. package/src/services/baseline-storage.ts +199 -0
  316. package/src/services/budget-evaluator.ts +182 -0
  317. package/src/services/config-manager.ts +23 -8
  318. package/src/services/file-loader.ts +3 -6
  319. package/src/services/profiler/profile-filter.ts +143 -0
  320. package/src/services/profiler/profile-parser.ts +194 -0
  321. package/src/services/profiler/profile-runner.ts +121 -0
  322. package/src/services/reporter-registry.ts +46 -81
  323. package/src/types/budgets.ts +180 -0
  324. package/src/types/cli.ts +5 -238
  325. package/src/types/core.ts +50 -10
  326. package/src/types/index.ts +5 -0
  327. package/src/types/interfaces.ts +16 -6
  328. package/src/types/profiler.ts +132 -0
  329. package/src/types/utility.ts +0 -10
  330. package/src/utils/identifiers.ts +58 -0
  331. package/src/utils/package.ts +35 -0
  332. package/src/utils/type-guards.ts +51 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utility functions for creating branded identifier types
3
+ *
4
+ * @module utils/identifiers
5
+ */
6
+ import type { RunId, TaskId } from "../types/budgets.cjs";
7
+ /**
8
+ * Create a RunId from a string (validation should happen elsewhere)
9
+ *
10
+ * @param id - The run identifier string (typically 7 alphanumeric characters)
11
+ * @returns A branded RunId
12
+ */
13
+ export declare const createRunId: (id: string) => RunId;
14
+ /**
15
+ * Create a TaskId from file, suite, and task names
16
+ *
17
+ * @param filePath - Path to the benchmark file
18
+ * @param suiteName - Name of the test suite
19
+ * @param taskName - Name of the benchmark task
20
+ * @returns A branded TaskId in the format `{filePath}/{suiteName}/{taskName}`
21
+ */
22
+ export declare function createTaskId(filePath: string, suiteName: string, taskName: string): TaskId;
23
+ /**
24
+ * Create a TaskId from a single string
25
+ *
26
+ * @param filePath - Path to the benchmark file
27
+ * @param suiteName - Name of the test suite
28
+ * @param taskName - Name of the benchmark task
29
+ * @returns A branded TaskId in the format `{filePath}/{suiteName}/{taskName}`
30
+ */
31
+ export declare function createTaskId(taskId: string): TaskId;
32
+ //# sourceMappingURL=identifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifiers.d.ts","sourceRoot":"","sources":["../../src/utils/identifiers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA4B;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,IAAI,MAAM,KAAG,KAAoB,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC;AAEV;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utility functions for creating branded identifier types
3
+ *
4
+ * @module utils/identifiers
5
+ */
6
+ import type { RunId, TaskId } from "../types/budgets.js";
7
+ /**
8
+ * Create a RunId from a string (validation should happen elsewhere)
9
+ *
10
+ * @param id - The run identifier string (typically 7 alphanumeric characters)
11
+ * @returns A branded RunId
12
+ */
13
+ export declare const createRunId: (id: string) => RunId;
14
+ /**
15
+ * Create a TaskId from file, suite, and task names
16
+ *
17
+ * @param filePath - Path to the benchmark file
18
+ * @param suiteName - Name of the test suite
19
+ * @param taskName - Name of the benchmark task
20
+ * @returns A branded TaskId in the format `{filePath}/{suiteName}/{taskName}`
21
+ */
22
+ export declare function createTaskId(filePath: string, suiteName: string, taskName: string): TaskId;
23
+ /**
24
+ * Create a TaskId from a single string
25
+ *
26
+ * @param filePath - Path to the benchmark file
27
+ * @param suiteName - Name of the test suite
28
+ * @param taskName - Name of the benchmark task
29
+ * @returns A branded TaskId in the format `{filePath}/{suiteName}/{taskName}`
30
+ */
31
+ export declare function createTaskId(taskId: string): TaskId;
32
+ //# sourceMappingURL=identifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifiers.d.ts","sourceRoot":"","sources":["../../src/utils/identifiers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,IAAI,MAAM,KAAG,KAAoB,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC;AAEV;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Utility functions for creating branded identifier types
3
+ *
4
+ * @module utils/identifiers
5
+ */
6
+ /**
7
+ * Create a RunId from a string (validation should happen elsewhere)
8
+ *
9
+ * @param id - The run identifier string (typically 7 alphanumeric characters)
10
+ * @returns A branded RunId
11
+ */
12
+ export const createRunId = (id) => id;
13
+ /**
14
+ * Create a TaskId from file, suite, and task names
15
+ *
16
+ * @param filePath - Path to the benchmark file
17
+ * @param suiteName - Name of the test suite
18
+ * @param taskName - Name of the benchmark task
19
+ * @returns A branded TaskId in the format `{filePath}/{suiteName}/{taskName}`
20
+ */
21
+ export function createTaskId(filePath, suiteName, taskName) {
22
+ if (suiteName !== undefined && taskName !== undefined) {
23
+ return `${filePath}/${suiteName}/${taskName}`;
24
+ }
25
+ return filePath;
26
+ }
27
+ //# sourceMappingURL=identifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifiers.js","sourceRoot":"","sources":["../../src/utils/identifiers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAU,EAAS,EAAE,CAAC,EAAW,CAAC;AA0B9D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,SAAkB,EAClB,QAAiB;IAEjB,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO,GAAG,QAAQ,IAAI,SAAS,IAAI,QAAQ,EAAY,CAAC;IAC1D,CAAC;IACD,OAAO,QAAkB,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Package Utilities
4
+ *
5
+ * Utilities for working with package.json files and package structure.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.findPackageRoot = void 0;
14
+ const promises_1 = require("node:fs/promises");
15
+ const node_path_1 = __importDefault(require("node:path"));
16
+ /**
17
+ * Find the nearest package.json and return its directory
18
+ *
19
+ * @param startDir - Directory to start searching from
20
+ * @returns Path to directory containing package.json
21
+ */
22
+ const findPackageRoot = async (startDir) => {
23
+ let currentDir = node_path_1.default.resolve(startDir);
24
+ const root = node_path_1.default.parse(currentDir).root;
25
+ while (currentDir !== root) {
26
+ try {
27
+ const packagePath = node_path_1.default.join(currentDir, 'package.json');
28
+ await (0, promises_1.readFile)(packagePath, 'utf-8');
29
+ return currentDir;
30
+ }
31
+ catch {
32
+ // package.json not found, go up one directory
33
+ currentDir = node_path_1.default.dirname(currentDir);
34
+ }
35
+ }
36
+ // No package.json found, return starting directory
37
+ return startDir;
38
+ };
39
+ exports.findPackageRoot = findPackageRoot;
40
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/utils/package.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;AAEH,+CAA4C;AAC5C,0DAA6B;AAE7B;;;;;GAKG;AACI,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IACzE,IAAI,UAAU,GAAG,mBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,mBAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEzC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YAC1D,MAAM,IAAA,mBAAQ,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;YAC9C,UAAU,GAAG,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAjBW,QAAA,eAAe,mBAiB1B"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Package Utilities
3
+ *
4
+ * Utilities for working with package.json files and package structure.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ /**
9
+ * Find the nearest package.json and return its directory
10
+ *
11
+ * @param startDir - Directory to start searching from
12
+ * @returns Path to directory containing package.json
13
+ */
14
+ export declare const findPackageRoot: (startDir: string) => Promise<string>;
15
+ //# sourceMappingURL=package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/utils/package.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAiBtE,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Package Utilities
3
+ *
4
+ * Utilities for working with package.json files and package structure.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ /**
9
+ * Find the nearest package.json and return its directory
10
+ *
11
+ * @param startDir - Directory to start searching from
12
+ * @returns Path to directory containing package.json
13
+ */
14
+ export declare const findPackageRoot: (startDir: string) => Promise<string>;
15
+ //# sourceMappingURL=package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/utils/package.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAiBtE,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Package Utilities
3
+ *
4
+ * Utilities for working with package.json files and package structure.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import { readFile } from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ /**
11
+ * Find the nearest package.json and return its directory
12
+ *
13
+ * @param startDir - Directory to start searching from
14
+ * @returns Path to directory containing package.json
15
+ */
16
+ export const findPackageRoot = async (startDir) => {
17
+ let currentDir = path.resolve(startDir);
18
+ const root = path.parse(currentDir).root;
19
+ while (currentDir !== root) {
20
+ try {
21
+ const packagePath = path.join(currentDir, 'package.json');
22
+ await readFile(packagePath, 'utf-8');
23
+ return currentDir;
24
+ }
25
+ catch {
26
+ // package.json not found, go up one directory
27
+ currentDir = path.dirname(currentDir);
28
+ }
29
+ }
30
+ // No package.json found, return starting directory
31
+ return startDir;
32
+ };
33
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/utils/package.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IACzE,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEzC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YAC1D,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;YAC9C,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Type Guard Utilities
4
+ *
5
+ * Reusable type guard functions for runtime type checking and narrowing.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.hasErrorCode = exports.isError = void 0;
9
+ /**
10
+ * Type guard to check if a value is an object (not null or array)
11
+ *
12
+ * @param value - Value to check
13
+ * @returns True if value is a non-null object
14
+ */
15
+ const isObject = (value) => {
16
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
17
+ };
18
+ /**
19
+ * Type guard to check if a value is an Error instance
20
+ *
21
+ * @param value - Value to check
22
+ * @returns True if value is an Error
23
+ */
24
+ const isError = (value) => {
25
+ return value instanceof Error;
26
+ };
27
+ exports.isError = isError;
28
+ /**
29
+ * Type guard to check if a value has a specific property
30
+ *
31
+ * @param value - Value to check
32
+ * @param property - Property name to check for
33
+ * @returns True if value is an object with the specified property
34
+ */
35
+ const hasProperty = (value, property) => {
36
+ return isObject(value) && property in value;
37
+ };
38
+ /**
39
+ * Type guard to check if an error has a code property
40
+ *
41
+ * @param error - Error to check
42
+ * @returns True if error has a code property
43
+ */
44
+ const hasErrorCode = (error) => {
45
+ return (0, exports.isError)(error) && hasProperty(error, 'code');
46
+ };
47
+ exports.hasErrorCode = hasErrorCode;
48
+ //# sourceMappingURL=type-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.js","sourceRoot":"","sources":["../../src/utils/type-guards.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE;IACpE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF;;;;;GAKG;AACI,MAAM,OAAO,GAAG,CAAC,KAAc,EAAkB,EAAE;IACxD,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC,CAAC;AAFW,QAAA,OAAO,WAElB;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAClB,KAAc,EACd,QAAW,EACkB,EAAE;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC;AAC9C,CAAC,CAAC;AAEF;;;;;GAKG;AACI,MAAM,YAAY,GAAG,CAC1B,KAAc,EACqB,EAAE;IACrC,OAAO,IAAA,eAAO,EAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC,CAAC;AAJW,QAAA,YAAY,gBAIvB"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Type Guard Utilities
3
+ *
4
+ * Reusable type guard functions for runtime type checking and narrowing.
5
+ */
6
+ /**
7
+ * Type guard to check if a value is an Error instance
8
+ *
9
+ * @param value - Value to check
10
+ * @returns True if value is an Error
11
+ */
12
+ export declare const isError: (value: unknown) => value is Error;
13
+ /**
14
+ * Type guard to check if an error has a code property
15
+ *
16
+ * @param error - Error to check
17
+ * @returns True if error has a code property
18
+ */
19
+ export declare const hasErrorCode: (error: unknown) => error is Error & {
20
+ code: string;
21
+ };
22
+ //# sourceMappingURL=type-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["../../src/utils/type-guards.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,KAEjD,CAAC;AAgBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO,OAAO,KACb,KAAK,IAAI,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAEjC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Type Guard Utilities
3
+ *
4
+ * Reusable type guard functions for runtime type checking and narrowing.
5
+ */
6
+ /**
7
+ * Type guard to check if a value is an Error instance
8
+ *
9
+ * @param value - Value to check
10
+ * @returns True if value is an Error
11
+ */
12
+ export declare const isError: (value: unknown) => value is Error;
13
+ /**
14
+ * Type guard to check if an error has a code property
15
+ *
16
+ * @param error - Error to check
17
+ * @returns True if error has a code property
18
+ */
19
+ export declare const hasErrorCode: (error: unknown) => error is Error & {
20
+ code: string;
21
+ };
22
+ //# sourceMappingURL=type-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["../../src/utils/type-guards.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,KAEjD,CAAC;AAgBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO,OAAO,KACb,KAAK,IAAI,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAEjC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Type Guard Utilities
3
+ *
4
+ * Reusable type guard functions for runtime type checking and narrowing.
5
+ */
6
+ /**
7
+ * Type guard to check if a value is an object (not null or array)
8
+ *
9
+ * @param value - Value to check
10
+ * @returns True if value is a non-null object
11
+ */
12
+ const isObject = (value) => {
13
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
14
+ };
15
+ /**
16
+ * Type guard to check if a value is an Error instance
17
+ *
18
+ * @param value - Value to check
19
+ * @returns True if value is an Error
20
+ */
21
+ export const isError = (value) => {
22
+ return value instanceof Error;
23
+ };
24
+ /**
25
+ * Type guard to check if a value has a specific property
26
+ *
27
+ * @param value - Value to check
28
+ * @param property - Property name to check for
29
+ * @returns True if value is an object with the specified property
30
+ */
31
+ const hasProperty = (value, property) => {
32
+ return isObject(value) && property in value;
33
+ };
34
+ /**
35
+ * Type guard to check if an error has a code property
36
+ *
37
+ * @param error - Error to check
38
+ * @returns True if error has a code property
39
+ */
40
+ export const hasErrorCode = (error) => {
41
+ return isError(error) && hasProperty(error, 'code');
42
+ };
43
+ //# sourceMappingURL=type-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.js","sourceRoot":"","sources":["../../src/utils/type-guards.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE;IACpE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAc,EAAkB,EAAE;IACxD,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAClB,KAAc,EACd,QAAW,EACkB,EAAE;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC;AAC9C,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAc,EACqB,EAAE;IACrC,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modestbench",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "A full-ass benchmarking framework for Node.js",
6
6
  "repository": {
@@ -16,9 +16,7 @@
16
16
  "engines": {
17
17
  "node": ">=20.0.0"
18
18
  },
19
- "bin": {
20
- "modestbench": "dist/cli/index.js"
21
- },
19
+ "bin": "./dist/cli/index.cjs",
22
20
  "main": "./dist/index.cjs",
23
21
  "types": "./dist/index.d.cts",
24
22
  "module": "./dist/index.js",
@@ -72,14 +70,14 @@
72
70
  "docs:preview": "astro preview --config astro.config.js",
73
71
  "fix": "run-s -sl fix:*",
74
72
  "fix:eslint": "eslint --fix .",
75
- "fix:format": "prettier --write . && markdownlint-cli2 --fix \"**/*.md\"",
76
73
  "fix:pkg": "npm pkg fix",
74
+ "fix:prettier": "prettier --write . && markdownlint-cli2 --fix \"**/*.md\"",
77
75
  "lint": "run-p -sl --aggregate-output lint:*",
78
76
  "lint-staged": "lint-staged",
79
77
  "lint:eslint": "eslint .",
80
- "lint:format": "prettier --check .",
81
78
  "lint:knip": "knip",
82
79
  "lint:markdown": "markdownlint-cli2 \"**/*.md\"",
80
+ "lint:prettier": "prettier --check .",
83
81
  "lint:spelling": "cspell .",
84
82
  "lint:types": "tsc --noEmit",
85
83
  "prepack": "run-s -s clean build",
@@ -99,7 +97,8 @@
99
97
  "cosmiconfig": "9.0.0",
100
98
  "cosmiconfig-typescript-loader": "6.2.0",
101
99
  "glob": "11.0.3",
102
- "tinybench": "5.0.1",
100
+ "minimatch": "10.0.3",
101
+ "tinybench": "5.1.0",
103
102
  "yargs": "18.0.0",
104
103
  "zod": "4.1.12"
105
104
  },
@@ -112,17 +111,17 @@
112
111
  "@stylistic/eslint-plugin": "5.5.0",
113
112
  "@types/node": "24.9.1",
114
113
  "@types/wallabyjs": "0.0.15",
115
- "@types/yargs": "17.0.33",
114
+ "@types/yargs": "17.0.34",
116
115
  "asciinema-player": "3.12.1",
117
116
  "astro": "5.15.1",
118
- "bupkis": "0.11.1",
117
+ "bupkis": "0.12.0",
119
118
  "cspell": "9.2.2",
120
119
  "eslint": "9.38.0",
121
120
  "eslint-plugin-jsonc": "2.21.0",
122
121
  "eslint-plugin-perfectionist": "4.15.1",
123
122
  "globals": "16.4.0",
124
123
  "husky": "9.1.7",
125
- "knip": "5.66.2",
124
+ "knip": "5.66.3",
126
125
  "lint-staged": "16.2.6",
127
126
  "markdownlint-cli2": "0.18.1",
128
127
  "markdownlint-cli2-formatter-pretty": "0.0.8",
@@ -207,6 +206,7 @@
207
206
  "tsdoc": true
208
207
  },
209
208
  "zshy": {
209
+ "bin": "./src/cli/index.ts",
210
210
  "exports": {
211
211
  ".": "./src/index.ts",
212
212
  "./cli": "./src/cli/index.ts",
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Analyze Command
3
+ *
4
+ * CLI command for analyzing code execution and identifying benchmark
5
+ * candidates. Uses Node.js V8 profiler to capture function execution data.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import type { ProfileConfig } from '../../types/profiler.js';
11
+ import type { CliContext } from '../index.js';
12
+
13
+ import { ProfileHumanReporter } from '../../reporters/profile-human.js';
14
+ import { filterProfile } from '../../services/profiler/profile-filter.js';
15
+ import { parseProfile } from '../../services/profiler/profile-parser.js';
16
+ import { runWithProfiling } from '../../services/profiler/profile-runner.js';
17
+ import { findPackageRoot } from '../../utils/package.js';
18
+
19
+ /**
20
+ * Analyze command options interface
21
+ */
22
+ export interface AnalyzeOptions {
23
+ /** Enable color output */
24
+ color?: boolean | undefined;
25
+
26
+ /** Command to analyze */
27
+ command?: string | undefined;
28
+
29
+ /** Working directory */
30
+ cwd: string;
31
+
32
+ /** Filter by file pattern */
33
+ filterFile?: string | undefined;
34
+
35
+ /** Group by file */
36
+ groupByFile?: boolean | undefined;
37
+
38
+ /** Input profile file */
39
+ input?: string | undefined;
40
+
41
+ /** Minimum execution percentage */
42
+ minPercent?: number | undefined;
43
+
44
+ /** Number of top functions to show */
45
+ top?: number | undefined;
46
+ }
47
+
48
+ /**
49
+ * Handle analyze command
50
+ */
51
+ export const handleAnalyzeCommand = async (
52
+ _context: CliContext,
53
+ options: AnalyzeOptions,
54
+ ): Promise<number> => {
55
+ try {
56
+ const startTime = Date.now();
57
+
58
+ // Run profiling or load existing profile
59
+ const logPath = options.input
60
+ ? options.input
61
+ : await runWithProfiling(options.command!, {
62
+ cwd: options.cwd,
63
+ });
64
+
65
+ const duration = Date.now() - startTime;
66
+
67
+ // Parse profile data
68
+ const profileData = await parseProfile(logPath);
69
+
70
+ // Find package root for smart detection
71
+ const packageRoot = await findPackageRoot(options.cwd);
72
+
73
+ // Apply filtering
74
+ const config: ProfileConfig = {
75
+ focus: options.filterFile ? [options.filterFile] : undefined,
76
+ groupByFile: options.groupByFile,
77
+ minExecutionPercent: options.minPercent,
78
+ smartDetection: true,
79
+ topN: options.top,
80
+ };
81
+
82
+ const filtered = filterProfile(profileData, config, packageRoot);
83
+
84
+ // Add command and duration to filtered data
85
+ filtered.command = options.command;
86
+ filtered.duration = duration;
87
+
88
+ // Report results
89
+ const reporter = new ProfileHumanReporter({
90
+ color: options.color,
91
+ groupByFile: options.groupByFile,
92
+ });
93
+
94
+ reporter.report(filtered);
95
+
96
+ return 0;
97
+ } catch (error) {
98
+ console.error('Analyze command failed:', error);
99
+ return 1;
100
+ }
101
+ };