create-appraisejs 0.1.10-alpha.8 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/README.md +52 -52
  2. package/dist/cli.e2e.test.d.ts +2 -0
  3. package/dist/cli.e2e.test.d.ts.map +1 -0
  4. package/dist/cli.e2e.test.js +73 -0
  5. package/dist/cli.e2e.test.js.map +1 -0
  6. package/dist/config.test.d.ts +2 -0
  7. package/dist/config.test.d.ts.map +1 -0
  8. package/dist/config.test.js +65 -0
  9. package/dist/config.test.js.map +1 -0
  10. package/dist/copy-template.test.d.ts +2 -0
  11. package/dist/copy-template.test.d.ts.map +1 -0
  12. package/dist/copy-template.test.js +71 -0
  13. package/dist/copy-template.test.js.map +1 -0
  14. package/dist/download-repo.test.d.ts +2 -0
  15. package/dist/download-repo.test.d.ts.map +1 -0
  16. package/dist/download-repo.test.js +14 -0
  17. package/dist/download-repo.test.js.map +1 -0
  18. package/dist/install.test.d.ts +2 -0
  19. package/dist/install.test.d.ts.map +1 -0
  20. package/dist/install.test.js +119 -0
  21. package/dist/install.test.js.map +1 -0
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +5 -0
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.test.d.ts +2 -0
  26. package/dist/prompts.test.d.ts.map +1 -0
  27. package/dist/prompts.test.js +58 -0
  28. package/dist/prompts.test.js.map +1 -0
  29. package/dist/scaffold-gitignore.d.ts +1 -0
  30. package/dist/scaffold-gitignore.d.ts.map +1 -1
  31. package/dist/scaffold-gitignore.js +3 -0
  32. package/dist/scaffold-gitignore.js.map +1 -1
  33. package/package.json +3 -2
  34. package/templates/default/.appraise-template-meta.json +2 -2
  35. package/templates/default/.env.example +2 -2
  36. package/templates/default/.vscode/settings.json +2 -1
  37. package/templates/default/README.md +53 -53
  38. package/templates/default/automation/mapping/locator-map.json +1 -14
  39. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  40. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  41. package/templates/default/automation/steps/actions/input.step.ts +84 -84
  42. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  43. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  44. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  45. package/templates/default/automation/steps/actions/wait.step.ts +90 -90
  46. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  47. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  48. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  49. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  50. package/templates/default/components.json +24 -24
  51. package/templates/default/cucumber.mjs +16 -16
  52. package/templates/default/eslint.config.mjs +16 -16
  53. package/templates/default/gitignore +3 -0
  54. package/templates/default/next-env.d.ts +6 -6
  55. package/templates/default/next.config.ts +11 -11
  56. package/templates/default/package-lock.json +146 -75
  57. package/templates/default/package.json +2 -1
  58. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  59. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  60. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  61. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  62. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  63. package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
  64. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  65. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  66. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  67. package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
  68. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  69. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  70. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  71. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  72. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  73. package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
  74. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
  75. package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
  76. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  77. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  78. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  79. package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
  80. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  81. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  82. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  83. package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
  84. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
  85. package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
  86. package/templates/default/packages/locator-picker-companion/package.json +17 -0
  87. package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
  88. package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
  89. package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  90. package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
  91. package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  92. package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
  93. package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
  94. package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
  95. package/templates/default/postcss.config.mjs +8 -8
  96. package/templates/default/prisma/dev.db +0 -0
  97. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  98. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  99. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  100. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  101. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  102. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  103. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  104. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  105. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  106. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  107. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  108. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  109. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  110. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  111. package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  112. package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  113. package/templates/default/prisma/schema.prisma +4 -0
  114. package/templates/default/scripts/install-playwright.ts +20 -0
  115. package/templates/default/scripts/protect-seeded-files.ts +38 -38
  116. package/templates/default/scripts/regenerate-features.ts +94 -94
  117. package/templates/default/scripts/setup-env.ts +19 -19
  118. package/templates/default/scripts/sync-all.ts +22 -66
  119. package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
  120. package/templates/default/scripts/sync-environments.ts +40 -21
  121. package/templates/default/scripts/sync-locator-groups.ts +410 -410
  122. package/templates/default/scripts/sync-locators.ts +398 -398
  123. package/templates/default/scripts/sync-modules.ts +341 -341
  124. package/templates/default/scripts/sync-tags.ts +2 -3
  125. package/templates/default/scripts/sync-template-step-groups.ts +0 -3
  126. package/templates/default/scripts/sync-template-steps.ts +37 -11
  127. package/templates/default/scripts/sync-test-cases.ts +68 -16
  128. package/templates/default/scripts/sync-test-suites.ts +7 -5
  129. package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
  130. package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
  131. package/templates/default/src/actions/environments/environment-actions.ts +188 -188
  132. package/templates/default/src/actions/locator/locator-actions.ts +490 -490
  133. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
  134. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
  135. package/templates/default/src/actions/modules/module-actions.ts +135 -135
  136. package/templates/default/src/actions/reports/report-actions.ts +51 -49
  137. package/templates/default/src/actions/review/review-actions.ts +147 -147
  138. package/templates/default/src/actions/settings/sync-actions.ts +46 -0
  139. package/templates/default/src/actions/tags/tag-actions.ts +107 -107
  140. package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
  141. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
  142. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
  143. package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
  144. package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
  145. package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
  146. package/templates/default/src/actions/user/user-actions.ts +13 -13
  147. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  148. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
  149. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  150. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
  151. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
  152. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  153. package/templates/default/src/app/(base)/layout.tsx +10 -10
  154. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  155. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  156. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  157. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  158. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  159. package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
  160. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
  161. package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
  162. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
  163. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
  164. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
  165. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
  166. package/templates/default/src/app/(base)/locators/page.tsx +13 -13
  167. package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
  168. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
  169. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
  170. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
  171. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
  172. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
  173. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
  174. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  175. package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
  176. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  177. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
  178. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
  179. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  180. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
  181. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  182. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  183. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
  184. package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
  185. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
  186. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  187. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  188. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  189. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  190. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  191. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
  192. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
  193. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
  194. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
  195. package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
  196. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
  197. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
  198. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
  199. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
  200. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
  201. package/templates/default/src/app/(base)/settings/page.tsx +30 -0
  202. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
  203. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  204. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  205. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  206. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
  207. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  208. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  209. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  210. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
  211. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
  213. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  214. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
  215. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
  216. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
  217. package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
  218. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
  219. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
  220. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
  221. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
  222. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  223. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  224. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  225. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
  226. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
  227. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  228. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  229. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
  230. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
  231. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
  232. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
  233. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  234. package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
  235. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
  236. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
  237. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
  238. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
  239. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
  240. package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
  241. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  242. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
  243. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  244. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  245. package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
  246. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
  247. package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
  248. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
  249. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
  250. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
  251. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  252. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  253. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  254. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  255. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  256. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  257. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  258. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
  259. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
  260. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
  261. package/templates/default/src/app/globals.css +147 -147
  262. package/templates/default/src/app/layout.tsx +4 -0
  263. package/templates/default/src/app/page.tsx +2 -0
  264. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  265. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  266. package/templates/default/src/components/base-node.tsx +21 -21
  267. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  268. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
  269. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  270. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  271. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  272. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  273. package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
  274. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  275. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
  276. package/templates/default/src/components/diagram/node-form.tsx +262 -262
  277. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  278. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  279. package/templates/default/src/components/form/error-message.tsx +7 -7
  280. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  281. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  282. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  283. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  284. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  285. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  286. package/templates/default/src/components/logo.tsx +15 -15
  287. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  288. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  289. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
  290. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  291. package/templates/default/src/components/navigation/nav-command.tsx +13 -0
  292. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  293. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  294. package/templates/default/src/components/node-header.tsx +159 -159
  295. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
  296. package/templates/default/src/components/table/table-actions.tsx +172 -172
  297. package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
  298. package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
  299. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
  300. package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
  301. package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
  302. package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
  303. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  304. package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
  305. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  306. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  307. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  308. package/templates/default/src/components/typography/page-header.tsx +7 -7
  309. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  310. package/templates/default/src/components/ui/alert.tsx +43 -43
  311. package/templates/default/src/components/ui/avatar.tsx +40 -40
  312. package/templates/default/src/components/ui/badge.tsx +29 -29
  313. package/templates/default/src/components/ui/button.tsx +47 -47
  314. package/templates/default/src/components/ui/calendar.tsx +158 -158
  315. package/templates/default/src/components/ui/card.tsx +43 -43
  316. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  317. package/templates/default/src/components/ui/command.tsx +135 -135
  318. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  319. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  320. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  321. package/templates/default/src/components/ui/data-table.tsx +261 -261
  322. package/templates/default/src/components/ui/dialog.tsx +97 -97
  323. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  324. package/templates/default/src/components/ui/input.tsx +22 -22
  325. package/templates/default/src/components/ui/kbd.tsx +28 -28
  326. package/templates/default/src/components/ui/label.tsx +19 -19
  327. package/templates/default/src/components/ui/loading.tsx +12 -12
  328. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  329. package/templates/default/src/components/ui/multi-select.tsx +142 -142
  330. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  331. package/templates/default/src/components/ui/popover.tsx +33 -33
  332. package/templates/default/src/components/ui/progress.tsx +25 -25
  333. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  334. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  335. package/templates/default/src/components/ui/select.tsx +151 -151
  336. package/templates/default/src/components/ui/separator.tsx +22 -22
  337. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  338. package/templates/default/src/components/ui/table.tsx +76 -76
  339. package/templates/default/src/components/ui/tabs.tsx +55 -55
  340. package/templates/default/src/components/ui/textarea.tsx +21 -21
  341. package/templates/default/src/components/ui/toast.tsx +113 -113
  342. package/templates/default/src/components/ui/toaster.tsx +26 -26
  343. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
  344. package/templates/default/src/config/db-config.ts +10 -10
  345. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  346. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  347. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
  348. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  349. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  350. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
  351. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  352. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  353. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  354. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  355. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  356. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  357. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
  358. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  359. package/templates/default/src/hooks/use-toast.ts +187 -187
  360. package/templates/default/src/lib/automation/paths.ts +42 -12
  361. package/templates/default/src/lib/automation/projection-service.ts +2 -1
  362. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  363. package/templates/default/src/lib/database-sync.ts +2 -7
  364. package/templates/default/src/lib/environment-file-utils.ts +184 -184
  365. package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
  366. package/templates/default/src/lib/executor/types.ts +2 -2
  367. package/templates/default/src/lib/feature-file-generator.ts +5 -66
  368. package/templates/default/src/lib/gherkin-parser.ts +259 -259
  369. package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
  370. package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
  371. package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
  372. package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
  373. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  374. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  375. package/templates/default/src/lib/process/task-spawner.ts +39 -2
  376. package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
  377. package/templates/default/src/lib/sync/sync-executor.ts +130 -0
  378. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
  379. package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
  380. package/templates/default/src/lib/sync/sync-registry.ts +149 -0
  381. package/templates/default/src/lib/tag-utils.ts +28 -0
  382. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  383. package/templates/default/src/lib/template-sync-utils.js +46 -46
  384. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  385. package/templates/default/src/lib/test-case-utils.ts +6 -6
  386. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  387. package/templates/default/src/lib/test-run/matching.ts +117 -0
  388. package/templates/default/src/lib/test-run/process-manager.ts +2 -0
  389. package/templates/default/src/lib/test-run/report-parser.ts +352 -316
  390. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
  391. package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
  392. package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
  393. package/templates/default/src/lib/test-suite-utils.ts +6 -0
  394. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  395. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  396. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  397. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  398. package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
  399. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
  400. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  401. package/templates/default/src/lib/utils.ts +31 -31
  402. package/templates/default/src/types/diagram/diagram.ts +34 -34
  403. package/templates/default/src/types/diagram/template-step.ts +11 -11
  404. package/templates/default/src/types/executor/browser.type.ts +1 -1
  405. package/templates/default/src/types/form/actionHandler.ts +6 -6
  406. package/templates/default/src/types/locator/locator.type.ts +11 -11
  407. package/templates/default/src/types/locator-picker.ts +65 -0
  408. package/templates/default/src/types/step/step.type.ts +1 -1
  409. package/templates/default/src/types/table/data-table.ts +6 -6
  410. package/templates/default/src/types/test-case-picker.ts +6 -0
  411. package/templates/default/src/types/test-suite-picker.ts +18 -0
  412. package/templates/default/tailwind.config.ts +62 -62
  413. package/templates/default/tsconfig.json +4 -1
  414. package/templates/default/appraisejs.config.json +0 -1
@@ -1,205 +1,205 @@
1
- import prisma from '@/config/db-config'
2
-
3
- /**
4
- * Represents a module path structure
5
- */
6
- export interface ModulePath {
7
- path: string
8
- name: string
9
- parentPath?: string
10
- }
11
-
12
- /**
13
- * Creates or finds a module by its path
14
- * @param modulePath - The module path (e.g., "/module1/submodule")
15
- * @param moduleName - The name of the module
16
- * @param parentId - Optional parent module ID
17
- * @returns Promise<string> - The ID of the created or found module
18
- */
19
- export async function createOrFindModule(modulePath: string, moduleName: string, parentId?: string): Promise<string> {
20
- try {
21
- // First, try to find existing module by name and parent
22
- const existingModule = await prisma.module.findFirst({
23
- where: {
24
- name: moduleName,
25
- parentId: parentId || null,
26
- },
27
- })
28
-
29
- if (existingModule) {
30
- return existingModule.id
31
- }
32
-
33
- // Create new module
34
- const newModule = await prisma.module.create({
35
- data: {
36
- name: moduleName,
37
- parentId: parentId || null,
38
- // Add description only if it's required by the schema
39
- // For now, we'll leave it empty since it's optional
40
- },
41
- })
42
-
43
- console.log(`Created module: ${moduleName} (${modulePath})`)
44
- return newModule.id
45
- } catch (error) {
46
- console.error(`Error creating module ${moduleName}:`, error)
47
- throw error
48
- }
49
- }
50
-
51
- /**
52
- * Builds the complete module hierarchy from a module path
53
- * @param modulePath - The module path (e.g., "/module1/submodule")
54
- * @returns Promise<string> - The ID of the leaf module
55
- */
56
- export async function buildModuleHierarchy(modulePath: string): Promise<string> {
57
- try {
58
- // Parse the module path
59
- const pathParts = modulePath.split('/').filter(part => part && part !== '')
60
-
61
- // Handle empty path (root level) - create/find a default root module
62
- if (pathParts.length === 0) {
63
- const rootModule = await prisma.module.findFirst({
64
- where: {
65
- name: 'root',
66
- parentId: null,
67
- },
68
- })
69
-
70
- if (rootModule) {
71
- return rootModule.id
72
- }
73
-
74
- // Create default root module
75
- const newRootModule = await prisma.module.create({
76
- data: {
77
- name: 'root',
78
- parentId: null,
79
- },
80
- })
81
-
82
- console.log(`Created root module for features without module path`)
83
- return newRootModule.id
84
- }
85
-
86
- let currentParentId: string | undefined
87
- let currentPath = ''
88
-
89
- // Create or find each module in the hierarchy
90
- for (let i = 0; i < pathParts.length; i++) {
91
- const moduleName = pathParts[i]
92
- currentPath += `/${moduleName}`
93
-
94
- const moduleId = await createOrFindModule(currentPath, moduleName, currentParentId)
95
-
96
- currentParentId = moduleId
97
- }
98
-
99
- return currentParentId!
100
- } catch (error) {
101
- console.error(`Error building module hierarchy for path ${modulePath}:`, error)
102
- throw error
103
- }
104
- }
105
-
106
- /**
107
- * Gets all existing modules as a flat list with their paths
108
- * @returns Promise<Array<{id: string, name: string, path: string, parentId: string | null}>>
109
- */
110
- export async function getAllModulesWithPaths(): Promise<
111
- Array<{
112
- id: string
113
- name: string
114
- path: string
115
- parentId: string | null
116
- }>
117
- > {
118
- try {
119
- const modules = await prisma.module.findMany({
120
- orderBy: [{ parentId: 'asc' }, { name: 'asc' }],
121
- })
122
-
123
- // Build paths for each module
124
- const modulesWithPaths = modules.map(module => {
125
- const path = buildModulePath(modules, module)
126
- return {
127
- id: module.id,
128
- name: module.name,
129
- path,
130
- parentId: module.parentId,
131
- }
132
- })
133
-
134
- return modulesWithPaths
135
- } catch (error) {
136
- console.error('Error fetching modules with paths:', error)
137
- throw error
138
- }
139
- }
140
-
141
- /**
142
- * Builds the full path for a module based on its hierarchy
143
- * @param allModules - All modules from the database
144
- * @param targetModule - The module to build the path for
145
- * @returns string - The full module path
146
- */
147
- function buildModulePath(
148
- allModules: Array<{ id: string; name: string; parentId: string | null }>,
149
- targetModule: { id: string; name: string; parentId: string | null },
150
- ): string {
151
- const pathParts: string[] = []
152
- let currentModule = targetModule
153
-
154
- // Traverse up the hierarchy
155
- while (currentModule) {
156
- pathParts.unshift(currentModule.name)
157
-
158
- if (currentModule.parentId) {
159
- currentModule = allModules.find(m => m.id === currentModule.parentId)!
160
- if (!currentModule) break
161
- } else {
162
- break
163
- }
164
- }
165
-
166
- return '/' + pathParts.join('/')
167
- }
168
-
169
- /**
170
- * Finds a module by its path
171
- * @param modulePath - The module path to find
172
- * @returns Promise<string | null> - The module ID or null if not found
173
- */
174
- export async function findModuleByPath(modulePath: string): Promise<string | null> {
175
- try {
176
- const modules = await prisma.module.findMany()
177
- const pathParts = modulePath.split('/').filter(part => part && part !== '')
178
-
179
- if (pathParts.length === 0) {
180
- return null
181
- }
182
-
183
- // Find the root module
184
- let currentModule = modules.find(m => m.name === pathParts[0] && !m.parentId)
185
- if (!currentModule) {
186
- return null
187
- }
188
-
189
- // Traverse down the hierarchy
190
- for (let i = 1; i < pathParts.length; i++) {
191
- const childModule = modules.find(m => m.name === pathParts[i] && m.parentId === currentModule!.id)
192
-
193
- if (!childModule) {
194
- return null
195
- }
196
-
197
- currentModule = childModule
198
- }
199
-
200
- return currentModule.id
201
- } catch (error) {
202
- console.error(`Error finding module by path ${modulePath}:`, error)
203
- return null
204
- }
205
- }
1
+ import prisma from '@/config/db-config'
2
+
3
+ /**
4
+ * Represents a module path structure
5
+ */
6
+ export interface ModulePath {
7
+ path: string
8
+ name: string
9
+ parentPath?: string
10
+ }
11
+
12
+ /**
13
+ * Creates or finds a module by its path
14
+ * @param modulePath - The module path (e.g., "/module1/submodule")
15
+ * @param moduleName - The name of the module
16
+ * @param parentId - Optional parent module ID
17
+ * @returns Promise<string> - The ID of the created or found module
18
+ */
19
+ export async function createOrFindModule(modulePath: string, moduleName: string, parentId?: string): Promise<string> {
20
+ try {
21
+ // First, try to find existing module by name and parent
22
+ const existingModule = await prisma.module.findFirst({
23
+ where: {
24
+ name: moduleName,
25
+ parentId: parentId || null,
26
+ },
27
+ })
28
+
29
+ if (existingModule) {
30
+ return existingModule.id
31
+ }
32
+
33
+ // Create new module
34
+ const newModule = await prisma.module.create({
35
+ data: {
36
+ name: moduleName,
37
+ parentId: parentId || null,
38
+ // Add description only if it's required by the schema
39
+ // For now, we'll leave it empty since it's optional
40
+ },
41
+ })
42
+
43
+ console.log(`Created module: ${moduleName} (${modulePath})`)
44
+ return newModule.id
45
+ } catch (error) {
46
+ console.error(`Error creating module ${moduleName}:`, error)
47
+ throw error
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Builds the complete module hierarchy from a module path
53
+ * @param modulePath - The module path (e.g., "/module1/submodule")
54
+ * @returns Promise<string> - The ID of the leaf module
55
+ */
56
+ export async function buildModuleHierarchy(modulePath: string): Promise<string> {
57
+ try {
58
+ // Parse the module path
59
+ const pathParts = modulePath.split('/').filter(part => part && part !== '')
60
+
61
+ // Handle empty path (root level) - create/find a default root module
62
+ if (pathParts.length === 0) {
63
+ const rootModule = await prisma.module.findFirst({
64
+ where: {
65
+ name: 'root',
66
+ parentId: null,
67
+ },
68
+ })
69
+
70
+ if (rootModule) {
71
+ return rootModule.id
72
+ }
73
+
74
+ // Create default root module
75
+ const newRootModule = await prisma.module.create({
76
+ data: {
77
+ name: 'root',
78
+ parentId: null,
79
+ },
80
+ })
81
+
82
+ console.log(`Created root module for features without module path`)
83
+ return newRootModule.id
84
+ }
85
+
86
+ let currentParentId: string | undefined
87
+ let currentPath = ''
88
+
89
+ // Create or find each module in the hierarchy
90
+ for (let i = 0; i < pathParts.length; i++) {
91
+ const moduleName = pathParts[i]
92
+ currentPath += `/${moduleName}`
93
+
94
+ const moduleId = await createOrFindModule(currentPath, moduleName, currentParentId)
95
+
96
+ currentParentId = moduleId
97
+ }
98
+
99
+ return currentParentId!
100
+ } catch (error) {
101
+ console.error(`Error building module hierarchy for path ${modulePath}:`, error)
102
+ throw error
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Gets all existing modules as a flat list with their paths
108
+ * @returns Promise<Array<{id: string, name: string, path: string, parentId: string | null}>>
109
+ */
110
+ export async function getAllModulesWithPaths(): Promise<
111
+ Array<{
112
+ id: string
113
+ name: string
114
+ path: string
115
+ parentId: string | null
116
+ }>
117
+ > {
118
+ try {
119
+ const modules = await prisma.module.findMany({
120
+ orderBy: [{ parentId: 'asc' }, { name: 'asc' }],
121
+ })
122
+
123
+ // Build paths for each module
124
+ const modulesWithPaths = modules.map(module => {
125
+ const path = buildModulePath(modules, module)
126
+ return {
127
+ id: module.id,
128
+ name: module.name,
129
+ path,
130
+ parentId: module.parentId,
131
+ }
132
+ })
133
+
134
+ return modulesWithPaths
135
+ } catch (error) {
136
+ console.error('Error fetching modules with paths:', error)
137
+ throw error
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Builds the full path for a module based on its hierarchy
143
+ * @param allModules - All modules from the database
144
+ * @param targetModule - The module to build the path for
145
+ * @returns string - The full module path
146
+ */
147
+ function buildModulePath(
148
+ allModules: Array<{ id: string; name: string; parentId: string | null }>,
149
+ targetModule: { id: string; name: string; parentId: string | null },
150
+ ): string {
151
+ const pathParts: string[] = []
152
+ let currentModule = targetModule
153
+
154
+ // Traverse up the hierarchy
155
+ while (currentModule) {
156
+ pathParts.unshift(currentModule.name)
157
+
158
+ if (currentModule.parentId) {
159
+ currentModule = allModules.find(m => m.id === currentModule.parentId)!
160
+ if (!currentModule) break
161
+ } else {
162
+ break
163
+ }
164
+ }
165
+
166
+ return '/' + pathParts.join('/')
167
+ }
168
+
169
+ /**
170
+ * Finds a module by its path
171
+ * @param modulePath - The module path to find
172
+ * @returns Promise<string | null> - The module ID or null if not found
173
+ */
174
+ export async function findModuleByPath(modulePath: string): Promise<string | null> {
175
+ try {
176
+ const modules = await prisma.module.findMany()
177
+ const pathParts = modulePath.split('/').filter(part => part && part !== '')
178
+
179
+ if (pathParts.length === 0) {
180
+ return null
181
+ }
182
+
183
+ // Find the root module
184
+ let currentModule = modules.find(m => m.name === pathParts[0] && !m.parentId)
185
+ if (!currentModule) {
186
+ return null
187
+ }
188
+
189
+ // Traverse down the hierarchy
190
+ for (let i = 1; i < pathParts.length; i++) {
191
+ const childModule = modules.find(m => m.name === pathParts[i] && m.parentId === currentModule!.id)
192
+
193
+ if (!childModule) {
194
+ return null
195
+ }
196
+
197
+ currentModule = childModule
198
+ }
199
+
200
+ return currentModule.id
201
+ } catch (error) {
202
+ console.error(`Error finding module by path ${modulePath}:`, error)
203
+ return null
204
+ }
205
+ }
@@ -1,71 +1,71 @@
1
- import { Module } from '@prisma/client'
2
-
3
- /**
4
- * Builds the hierarchical path for a module based on its parent modules
5
- * @param modules - Array of all modules
6
- * @param selectedModule - The module to get the path for
7
- * @returns The hierarchical path as a string (e.g., "/user/user profile")
8
- */
9
- export function buildModulePath(modules: Module[], selectedModule: Module): string {
10
- const path: string[] = []
11
- let currentModule: Module | null = selectedModule
12
-
13
- // Build path from current module up to root
14
- while (currentModule) {
15
- path.unshift(currentModule.name)
16
- currentModule = modules.find(m => m.id === currentModule?.parentId) || null
17
- }
18
-
19
- // Return path with leading slash
20
- return `/${path.join('/')}`
21
- }
22
-
23
- /**
24
- * Alternative implementation that can handle modules with parent relationships
25
- * This version works with the current data structure where we have parent info
26
- */
27
- export function buildModulePathFromParent(
28
- modules: (Module & { parent: { name: string } })[],
29
- selectedModule: Module & { parent: { name: string } },
30
- ): string {
31
- const path: string[] = []
32
- let currentModule: (Module & { parent: { name: string } }) | null = selectedModule
33
-
34
- // Build path from current module up to root
35
- while (currentModule) {
36
- path.unshift(currentModule.name)
37
-
38
- if (currentModule.parent?.name) {
39
- // Find the parent module in the modules array
40
- const parentModule = modules.find(m => m.name === currentModule?.parent?.name)
41
- currentModule = parentModule || null
42
- } else {
43
- // No parent, we've reached the root
44
- currentModule = null
45
- }
46
- }
47
-
48
- // Return path with leading slash
49
- return `/${path.join('/')}`
50
- }
51
-
52
- /**
53
- * Builds paths for all modules in a single pass for better performance
54
- * @param modules - Array of all modules with parent info
55
- * @returns Map of module ID to path string
56
- */
57
- export function buildAllModulePaths(modules: (Module & { parent: { name: string } })[]): Map<string, string> {
58
- const pathMap = new Map<string, string>()
59
-
60
- // First pass: create a map for quick lookup
61
- const moduleMap = new Map<string, Module & { parent: { name: string } }>()
62
- modules.forEach(module => moduleMap.set(module.id, module))
63
-
64
- // Second pass: build paths for each module
65
- modules.forEach(module => {
66
- const path = buildModulePathFromParent(modules, module)
67
- pathMap.set(module.id, path)
68
- })
69
-
70
- return pathMap
71
- }
1
+ import { Module } from '@prisma/client'
2
+
3
+ /**
4
+ * Builds the hierarchical path for a module based on its parent modules
5
+ * @param modules - Array of all modules
6
+ * @param selectedModule - The module to get the path for
7
+ * @returns The hierarchical path as a string (e.g., "/user/user profile")
8
+ */
9
+ export function buildModulePath(modules: Module[], selectedModule: Module): string {
10
+ const path: string[] = []
11
+ let currentModule: Module | null = selectedModule
12
+
13
+ // Build path from current module up to root
14
+ while (currentModule) {
15
+ path.unshift(currentModule.name)
16
+ currentModule = modules.find(m => m.id === currentModule?.parentId) || null
17
+ }
18
+
19
+ // Return path with leading slash
20
+ return `/${path.join('/')}`
21
+ }
22
+
23
+ /**
24
+ * Alternative implementation that can handle modules with parent relationships
25
+ * This version works with the current data structure where we have parent info
26
+ */
27
+ export function buildModulePathFromParent(
28
+ modules: (Module & { parent: { name: string } })[],
29
+ selectedModule: Module & { parent: { name: string } },
30
+ ): string {
31
+ const path: string[] = []
32
+ let currentModule: (Module & { parent: { name: string } }) | null = selectedModule
33
+
34
+ // Build path from current module up to root
35
+ while (currentModule) {
36
+ path.unshift(currentModule.name)
37
+
38
+ if (currentModule.parent?.name) {
39
+ // Find the parent module in the modules array
40
+ const parentModule = modules.find(m => m.name === currentModule?.parent?.name)
41
+ currentModule = parentModule || null
42
+ } else {
43
+ // No parent, we've reached the root
44
+ currentModule = null
45
+ }
46
+ }
47
+
48
+ // Return path with leading slash
49
+ return `/${path.join('/')}`
50
+ }
51
+
52
+ /**
53
+ * Builds paths for all modules in a single pass for better performance
54
+ * @param modules - Array of all modules with parent info
55
+ * @returns Map of module ID to path string
56
+ */
57
+ export function buildAllModulePaths(modules: (Module & { parent: { name: string } })[]): Map<string, string> {
58
+ const pathMap = new Map<string, string>()
59
+
60
+ // First pass: create a map for quick lookup
61
+ const moduleMap = new Map<string, Module & { parent: { name: string } }>()
62
+ modules.forEach(module => moduleMap.set(module.id, module))
63
+
64
+ // Second pass: build paths for each module
65
+ modules.forEach(module => {
66
+ const path = buildModulePathFromParent(modules, module)
67
+ pathMap.set(module.id, path)
68
+ })
69
+
70
+ return pathMap
71
+ }
@@ -7,6 +7,7 @@ export interface SpawnerOptions extends ExecaOptions {
7
7
  prefixLogs?: boolean
8
8
  logPrefix?: string
9
9
  captureOutput?: boolean
10
+ retainProcessRecord?: boolean
10
11
  }
11
12
 
12
13
  export interface SpawnedProcess {
@@ -28,8 +29,29 @@ export class TaskSpawner extends EventEmitter {
28
29
  private processCounter = 0
29
30
  private outputBuffers: Map<string, { stdout: string; stderr: string }> = new Map()
30
31
 
32
+ private scheduleProcessCleanup(processName: string, spawnedProcess: SpawnedProcess): void {
33
+ setImmediate(() => {
34
+ spawnedProcess.output.stdout.length = 0
35
+ spawnedProcess.output.stderr.length = 0
36
+ this.outputBuffers.delete(processName)
37
+ this.processes.delete(processName)
38
+ })
39
+ }
40
+
41
+ removeProcess(processName: string): boolean {
42
+ this.outputBuffers.delete(processName)
43
+ return this.processes.delete(processName)
44
+ }
45
+
31
46
  async spawn(command: string, args: string[] = [], options: SpawnerOptions = {}): Promise<SpawnedProcess> {
32
- const { streamLogs = true, prefixLogs = true, logPrefix, captureOutput = false, ...spawnOptions } = options
47
+ const {
48
+ streamLogs = true,
49
+ prefixLogs = true,
50
+ logPrefix,
51
+ captureOutput = false,
52
+ retainProcessRecord = true,
53
+ ...spawnOptions
54
+ } = options
33
55
 
34
56
  const processName = logPrefix || `${command}_${++this.processCounter}`
35
57
  const spawnedProcess: SpawnedProcess = {
@@ -49,6 +71,7 @@ export class TaskSpawner extends EventEmitter {
49
71
  const stdioConfig = captureOutput ? 'pipe' : streamLogs ? 'inherit' : 'pipe'
50
72
  const childProcess = execa(command, args, {
51
73
  stdio: stdioConfig,
74
+ reject: false,
52
75
  ...spawnOptions,
53
76
  })
54
77
 
@@ -63,6 +86,7 @@ export class TaskSpawner extends EventEmitter {
63
86
  streamLogs,
64
87
  prefixLogs,
65
88
  captureOutput,
89
+ retainProcessRecord,
66
90
  stdioConfig,
67
91
  })
68
92
 
@@ -140,10 +164,11 @@ export class TaskSpawner extends EventEmitter {
140
164
  streamLogs: boolean
141
165
  prefixLogs: boolean
142
166
  captureOutput: boolean
167
+ retainProcessRecord: boolean
143
168
  stdioConfig: string | string[]
144
169
  },
145
170
  ): void {
146
- const { streamLogs, prefixLogs, captureOutput, stdioConfig } = options
171
+ const { streamLogs, prefixLogs, captureOutput, retainProcessRecord, stdioConfig } = options
147
172
  const { process: childProcess, name } = spawnedProcess
148
173
 
149
174
  if (stdioConfig === 'pipe') {
@@ -201,13 +226,23 @@ export class TaskSpawner extends EventEmitter {
201
226
  spawnedProcess.isRunning = false
202
227
  spawnedProcess.exitCode = code
203
228
  spawnedProcess.endTime = new Date()
229
+
230
+ if (!retainProcessRecord) {
231
+ this.scheduleProcessCleanup(name, spawnedProcess)
232
+ }
233
+
204
234
  this.emit('exit', { processName: name, code })
205
235
  })
206
236
 
207
237
  childProcess.on('error', (error: Error) => {
238
+ this.outputBuffers.delete(name)
208
239
  spawnedProcess.isRunning = false
209
240
  spawnedProcess.endTime = new Date()
210
241
 
242
+ if (!retainProcessRecord) {
243
+ this.scheduleProcessCleanup(name, spawnedProcess)
244
+ }
245
+
211
246
  if (streamLogs) {
212
247
  const prefix = prefixLogs ? `[${name}] ` : ''
213
248
  console.error(`${prefix}ERROR: ${error.message}`)
@@ -234,3 +269,5 @@ export const spawnTask = (command: string, args: string[] = [], options: Spawner
234
269
  export const killTask = (processName: string, signal?: NodeJS.Signals) => taskSpawner.killProcess(processName, signal)
235
270
 
236
271
  export const waitForTask = (processName: string) => taskSpawner.waitForProcess(processName)
272
+
273
+ export const removeTask = (processName: string) => taskSpawner.removeProcess(processName)