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
@@ -26,12 +26,12 @@ import {
26
26
  * Init command options interface
27
27
  */
28
28
  interface InitOptions {
29
- configType: 'js' | 'json' | 'ts' | 'yaml';
30
- cwd: string;
31
- examples: boolean;
29
+ configType?: 'js' | 'json' | 'ts' | 'yaml';
30
+ cwd?: string;
31
+ examples?: boolean;
32
32
  force?: boolean | undefined;
33
33
  quiet?: boolean | undefined;
34
- type: 'advanced' | 'basic' | 'library';
34
+ type?: 'advanced' | 'basic' | 'library';
35
35
  verbose?: boolean | undefined;
36
36
  yes?: boolean | undefined;
37
37
  }
@@ -244,7 +244,7 @@ export default {
244
244
  /**
245
245
  * Prompt user for confirmation with Y/n default to Yes
246
246
  */
247
- const promptUser = async (question: string): Promise<boolean> => {
247
+ const _promptUser = async (question: string): Promise<boolean> => {
248
248
  const rl = createInterface({
249
249
  input: process.stdin,
250
250
  output: process.stdout,
@@ -268,7 +268,13 @@ export const handleInitCommand = async (
268
268
  options: InitOptions,
269
269
  ): Promise<number> => {
270
270
  try {
271
- const template = PROJECT_TEMPLATES[options.type];
271
+ // Apply defaults for required options
272
+ const type = options.type ?? 'basic';
273
+ const cwd = options.cwd ?? process.cwd();
274
+ const configType = options.configType ?? 'json';
275
+ const examples = options.examples ?? false;
276
+
277
+ const template = PROJECT_TEMPLATES[type];
272
278
 
273
279
  if (!options.quiet) {
274
280
  console.log(`Initializing ${template.name}...`);
@@ -278,7 +284,7 @@ export const handleInitCommand = async (
278
284
 
279
285
  // Check if project already exists
280
286
  if (!options.force) {
281
- const hasConflicts = await checkForConflicts(options);
287
+ const hasConflicts = await checkForConflicts(cwd, configType);
282
288
  if (hasConflicts) {
283
289
  console.error('Project files already exist. Use --force to overwrite.');
284
290
  return 1; // Already initialized
@@ -286,24 +292,27 @@ export const handleInitCommand = async (
286
292
  }
287
293
 
288
294
  // Create directory structure
289
- await createDirectories(template.directories, options);
295
+ await createDirectories(template.directories, cwd);
290
296
 
291
297
  // Create configuration file
292
- await createConfigFile(template.configOptions, options);
298
+ await createConfigFile(template.configOptions, cwd, configType);
293
299
 
294
300
  // Create example benchmarks if requested
295
- if (options.examples) {
296
- await createExampleBenchmarks(options);
301
+ if (examples) {
302
+ await createExampleBenchmarks(cwd);
297
303
  }
298
304
 
299
305
  // Create additional files
300
- await createAdditionalFiles(options);
306
+ await createAdditionalFiles(cwd, {
307
+ quiet: options.quiet,
308
+ yes: options.yes,
309
+ });
301
310
 
302
311
  if (!options.quiet) {
303
312
  console.log('✅ Project initialized successfully!');
304
313
  console.log();
305
314
  console.log('Next steps:');
306
- if (options.examples) {
315
+ if (examples) {
307
316
  console.log(' 1. Run example benchmarks: modestbench run');
308
317
  } else {
309
318
  console.log(
@@ -337,15 +346,15 @@ export const handleInitCommand = async (
337
346
  /**
338
347
  * Check for existing files that would conflict
339
348
  */
340
- const checkForConflicts = async (options: InitOptions): Promise<boolean> => {
341
- const filesToCheck = [
342
- 'modestbench.config.' + options.configType,
343
- 'benchmarks',
344
- ];
349
+ const checkForConflicts = async (
350
+ cwd: string,
351
+ configType: string,
352
+ ): Promise<boolean> => {
353
+ const filesToCheck = ['modestbench.config.' + configType, 'benchmarks'];
345
354
 
346
355
  for (const file of filesToCheck) {
347
356
  try {
348
- await access(resolve(options.cwd, file));
357
+ await access(resolve(cwd, file));
349
358
  return true; // File exists, conflict detected
350
359
  } catch {
351
360
  // File doesn't exist, no conflict
@@ -355,139 +364,13 @@ const checkForConflicts = async (options: InitOptions): Promise<boolean> => {
355
364
  return false;
356
365
  };
357
366
 
358
- /**
359
- * Handle .gitignore file creation or modification
360
- */
361
- const handleGitignore = async (options: InitOptions): Promise<void> => {
362
- const gitignorePath = resolve(options.cwd, '.gitignore');
363
- const modestbenchEntry = '.modestbench/';
364
-
365
- // Default .gitignore content for new files
366
- const defaultGitignoreContent = `# ModestBench
367
- benchmark-results/
368
- .modestbench/
369
-
370
- # Dependencies
371
- node_modules/
372
-
373
- # Environment
374
- .env
375
- .env.local
376
-
377
- # Logs
378
- *.log
379
- npm-debug.log*
380
- yarn-debug.log*
381
- yarn-error.log*
382
-
383
- # OS
384
- .DS_Store
385
- Thumbs.db
386
- `;
387
-
388
- try {
389
- // Check if .gitignore exists
390
- let gitignoreExists = false;
391
- try {
392
- await access(gitignorePath);
393
- gitignoreExists = true;
394
- } catch {
395
- // File doesn't exist
396
- }
397
-
398
- if (!gitignoreExists) {
399
- // Create new .gitignore with full content
400
- await writeFile(gitignorePath, defaultGitignoreContent, 'utf8');
401
- if (options.verbose) {
402
- console.log(' ✓ .gitignore');
403
- }
404
- return;
405
- }
406
-
407
- // File exists, check if .modestbench/ is already present
408
- const existingContent = await readFile(gitignorePath, 'utf8');
409
-
410
- // Check if .modestbench/ is already in the file
411
- const hasModestbenchEntry = existingContent
412
- .split('\n')
413
- .some((line) => line.trim() === modestbenchEntry);
414
-
415
- if (hasModestbenchEntry) {
416
- // Already has the entry, nothing to do
417
- if (options.verbose) {
418
- console.log(' ✓ .gitignore (already contains .modestbench/)');
419
- }
420
- return;
421
- }
422
-
423
- // Determine if we should prompt or auto-add
424
- let shouldAdd = false;
425
-
426
- if (options.yes || options.quiet) {
427
- // Auto-accept in non-interactive mode
428
- shouldAdd = true;
429
- } else {
430
- // Prompt the user
431
- console.log();
432
- console.log(
433
- 'The .modestbench/ directory stores benchmark history and should typically',
434
- );
435
- console.log('not be committed to version control.');
436
- console.log();
437
-
438
- shouldAdd = await promptUser(
439
- 'Would you like to add .modestbench/ to .gitignore? (Y/n) ',
440
- );
441
- }
442
-
443
- if (shouldAdd) {
444
- // Append .modestbench/ to existing .gitignore
445
- let contentToAppend = '';
446
-
447
- // Ensure file ends with newline
448
- if (!existingContent.endsWith('\n')) {
449
- contentToAppend += '\n';
450
- }
451
-
452
- // Add a blank line if the file doesn't end with one
453
- if (!existingContent.endsWith('\n\n') && existingContent.trim() !== '') {
454
- contentToAppend += '\n';
455
- }
456
-
457
- // Add comment and entry
458
- contentToAppend += '# ModestBench history\n';
459
- contentToAppend += modestbenchEntry + '\n';
460
-
461
- await appendFile(gitignorePath, contentToAppend, 'utf8');
462
-
463
- if (options.verbose || !options.quiet) {
464
- console.log(' ✓ Added .modestbench/ to .gitignore');
465
- }
466
- } else {
467
- if (options.verbose) {
468
- console.log(' ⊘ Skipped adding .modestbench/ to .gitignore');
469
- }
470
- }
471
- } catch (error) {
472
- // Non-critical, just warn
473
- console.warn(
474
- 'Warning: Could not create/modify .gitignore file:',
475
- error instanceof Error ? error.message : String(error),
476
- );
477
- }
478
- };
479
-
480
367
  /**
481
368
  * Create additional project files
482
369
  */
483
- const createAdditionalFiles = async (options: InitOptions): Promise<void> => {
484
- if (!options.quiet) {
485
- console.log('Creating additional files...');
486
- }
487
-
488
- // Handle .gitignore
489
- await handleGitignore(options);
490
-
370
+ const createAdditionalFiles = async (
371
+ cwd: string,
372
+ options?: { quiet?: boolean; yes?: boolean },
373
+ ): Promise<void> => {
491
374
  // Create README.md
492
375
  const readmeContent = `# Benchmark Project
493
376
 
@@ -520,15 +403,74 @@ Create new benchmark files in the \`benchmarks/\` directory. See the examples fo
520
403
  `;
521
404
 
522
405
  try {
523
- const readmePath = resolve(options.cwd, 'README.md');
406
+ const readmePath = resolve(cwd, 'README.md');
524
407
  await writeFile(readmePath, readmeContent, 'utf8');
525
- if (options.verbose) {
526
- console.log(' ✓ README.md');
527
- }
528
408
  } catch {
529
409
  // Non-critical, just warn
530
410
  console.warn('Warning: Could not create README.md file');
531
411
  }
412
+
413
+ // Create or update .gitignore
414
+ await createOrUpdateGitignore(cwd, options);
415
+ };
416
+
417
+ /**
418
+ * Create or update .gitignore file to include ModestBench directories
419
+ */
420
+ const createOrUpdateGitignore = async (
421
+ cwd: string,
422
+ options?: { quiet?: boolean; yes?: boolean },
423
+ ): Promise<void> => {
424
+ const gitignorePath = resolve(cwd, '.gitignore');
425
+ const modestbenchEntry = '.modestbench/';
426
+ const modestbenchSection = `\n# ModestBench history\n${modestbenchEntry}\n`;
427
+
428
+ try {
429
+ // Check if .gitignore exists
430
+ let existingContent = '';
431
+ try {
432
+ existingContent = await readFile(gitignorePath, 'utf8');
433
+ } catch {
434
+ // File doesn't exist, will create new one
435
+ }
436
+
437
+ if (existingContent) {
438
+ // File exists, check if .modestbench/ is already present
439
+ if (existingContent.includes(modestbenchEntry)) {
440
+ // Already present, nothing to do
441
+ return;
442
+ }
443
+
444
+ // Append .modestbench/ entry (--yes or --quiet means auto-accept)
445
+ if (options?.yes || options?.quiet) {
446
+ // Ensure content ends with newline
447
+ const contentToAppend = existingContent.endsWith('\n')
448
+ ? modestbenchSection
449
+ : `\n${modestbenchSection}`;
450
+ await appendFile(gitignorePath, contentToAppend, 'utf8');
451
+ }
452
+ } else {
453
+ // Create new .gitignore with common entries
454
+ const newContent = `# Dependencies
455
+ node_modules/
456
+
457
+ # Build output
458
+ dist/
459
+ build/
460
+ *.log
461
+
462
+ # Test coverage
463
+ coverage/
464
+
465
+ # Benchmark output
466
+ benchmark-results/
467
+ ${modestbenchSection}`;
468
+ await writeFile(gitignorePath, newContent, 'utf8');
469
+ }
470
+ } catch {
471
+ // Non-critical, just warn
472
+ console.warn('Warning: Could not create/update .gitignore file');
473
+ }
532
474
  };
533
475
 
534
476
  /**
@@ -536,18 +478,15 @@ Create new benchmark files in the \`benchmarks/\` directory. See the examples fo
536
478
  */
537
479
  const createConfigFile = async (
538
480
  configOptions: any,
539
- options: InitOptions,
481
+ cwd: string,
482
+ configType: string,
540
483
  ): Promise<void> => {
541
- const filename = `modestbench.config.${options.configType}`;
542
- const filePath = resolve(options.cwd, filename);
543
-
544
- if (!options.quiet) {
545
- console.log(`Creating configuration file: ${filename}`);
546
- }
484
+ const filename = `modestbench.config.${configType}`;
485
+ const filePath = resolve(cwd, filename);
547
486
 
548
487
  let content: string;
549
488
 
550
- switch (options.configType) {
489
+ switch (configType) {
551
490
  case 'js':
552
491
  content = `export default ${JSON.stringify(configOptions, null, 2)};\n`;
553
492
  break;
@@ -572,15 +511,12 @@ export default config;
572
511
 
573
512
  default:
574
513
  throw new UnsupportedConfigFormatError(
575
- `Unsupported config format: ${options.configType}`,
514
+ `Unsupported config format: ${configType}`,
576
515
  );
577
516
  }
578
517
 
579
518
  try {
580
519
  await writeFile(filePath, content, 'utf8');
581
- if (options.verbose) {
582
- console.log(` ✓ ${filename}`);
583
- }
584
520
  } catch (error) {
585
521
  throw new InvalidArgumentError(
586
522
  `Failed to create config file: ${error instanceof Error ? error.message : String(error)}`,
@@ -594,19 +530,12 @@ export default config;
594
530
  */
595
531
  const createDirectories = async (
596
532
  directories: readonly string[],
597
- options: InitOptions,
533
+ cwd: string,
598
534
  ): Promise<void> => {
599
- if (!options.quiet) {
600
- console.log('Creating directories...');
601
- }
602
-
603
535
  for (const dir of directories) {
604
- const dirPath = resolve(options.cwd, dir);
536
+ const dirPath = resolve(cwd, dir);
605
537
  try {
606
538
  await mkdir(dirPath, { recursive: true });
607
- if (options.verbose) {
608
- console.log(` ✓ ${dir}/`);
609
- }
610
539
  } catch (error) {
611
540
  throw new InvalidArgumentError(
612
541
  `Failed to create directory ${dir}: ${error instanceof Error ? error.message : String(error)}`,
@@ -619,21 +548,14 @@ const createDirectories = async (
619
548
  /**
620
549
  * Create example benchmark files
621
550
  */
622
- const createExampleBenchmarks = async (options: InitOptions): Promise<void> => {
623
- if (!options.quiet) {
624
- console.log('Creating example benchmarks...');
625
- }
626
-
627
- const benchmarksDir = resolve(options.cwd, 'benchmarks');
551
+ const createExampleBenchmarks = async (cwd: string): Promise<void> => {
552
+ const benchmarksDir = resolve(cwd, 'benchmarks');
628
553
 
629
554
  for (const [name, example] of Object.entries(EXAMPLE_BENCHMARKS)) {
630
555
  const filePath = join(benchmarksDir, example.filename);
631
556
 
632
557
  try {
633
558
  await writeFile(filePath, example.content, 'utf8');
634
- if (options.verbose) {
635
- console.log(` ✓ ${example.filename}`);
636
- }
637
559
  } catch (error) {
638
560
  throw new InvalidArgumentError(
639
561
  `Failed to create example ${name}: ${error instanceof Error ? error.message : String(error)}`,