@codeyam/codeyam-cli 0.1.0-staging.596f0eb → 0.1.0-staging.76566f9

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 (354) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +2 -1
  4. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +2 -0
  5. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +22 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.ts +23 -1
  7. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +401 -106
  8. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +60 -0
  9. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +734 -45
  10. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +2 -1
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +715 -0
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +233 -75
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +19 -1
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +34 -1
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +23 -0
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.ts +98 -0
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +34 -1
  18. package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +236 -24
  19. package/analyzer-template/packages/ai/src/lib/generateChangesEntityKeyAttributes.ts +18 -1
  20. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +41 -0
  21. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +37 -4
  22. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +5 -0
  23. package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +213 -12
  24. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +36 -25
  25. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +114 -11
  26. package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +143 -31
  27. package/analyzer-template/packages/ai/src/lib/guessScenarioDataFromDescription.ts +8 -2
  28. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +7 -0
  29. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +42 -2
  30. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +38 -2
  31. package/analyzer-template/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.ts +28 -2
  32. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +5 -0
  33. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +8 -1
  34. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +127 -43
  35. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +158 -0
  36. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +405 -45
  37. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.ts +1 -1
  38. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +260 -133
  39. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +10 -5
  40. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +77 -83
  41. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +2 -5
  42. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +196 -86
  43. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts +15 -0
  44. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts.map +1 -0
  45. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js +31 -0
  46. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js.map +1 -0
  47. package/analyzer-template/packages/aws/package.json +1 -1
  48. package/analyzer-template/packages/aws/s3/index.ts +1 -0
  49. package/analyzer-template/packages/aws/src/lib/s3/checkS3ObjectExists.ts +47 -0
  50. package/analyzer-template/packages/database/src/lib/kysely/db.ts +4 -4
  51. package/analyzer-template/packages/database/src/lib/kysely/tableRelations.ts +2 -2
  52. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +20 -9
  53. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +9 -4
  54. package/analyzer-template/packages/generate/src/lib/deepMerge.ts +26 -1
  55. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -2
  56. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +2 -2
  57. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tableRelations.d.ts +2 -2
  58. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts +8 -1
  59. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  60. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +14 -7
  61. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -1
  62. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
  63. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
  64. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts +1 -1
  65. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.map +1 -1
  66. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
  67. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
  68. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  69. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.d.ts.map +1 -1
  70. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js +27 -1
  71. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js.map +1 -1
  72. package/analyzer-template/packages/github/dist/types/index.d.ts +4 -3
  73. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  74. package/analyzer-template/packages/github/dist/types/index.js +1 -0
  75. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  76. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +31 -1
  77. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  78. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts +51 -1
  79. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
  80. package/analyzer-template/packages/github/dist/types/src/types/Scenario.js +21 -1
  81. package/analyzer-template/packages/github/dist/types/src/types/Scenario.js.map +1 -1
  82. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +48 -0
  83. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  84. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  85. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
  86. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  87. package/analyzer-template/packages/types/index.ts +8 -0
  88. package/analyzer-template/packages/types/src/types/Analysis.ts +32 -1
  89. package/analyzer-template/packages/types/src/types/Scenario.ts +75 -6
  90. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +49 -0
  91. package/analyzer-template/packages/ui-components/src/components/ScenarioDetailInteractiveView.tsx +23 -7
  92. package/analyzer-template/packages/utils/dist/types/index.d.ts +4 -3
  93. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  94. package/analyzer-template/packages/utils/dist/types/index.js +1 -0
  95. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  96. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +31 -1
  97. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  98. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts +51 -1
  99. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
  100. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.js +21 -1
  101. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.js.map +1 -1
  102. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +48 -0
  103. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  104. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  105. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
  106. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  107. package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +27 -0
  108. package/analyzer-template/playwright/takeElementScreenshot.ts +26 -11
  109. package/analyzer-template/playwright/takeScreenshot.ts +9 -7
  110. package/analyzer-template/project/constructMockCode.ts +286 -84
  111. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +77 -37
  112. package/analyzer-template/project/reconcileMockDataKeys.ts +5 -2
  113. package/analyzer-template/project/runMultiScenarioServer.ts +11 -10
  114. package/analyzer-template/project/serverOnlyModules.ts +71 -23
  115. package/analyzer-template/project/start.ts +10 -0
  116. package/analyzer-template/project/startScenarioCapture.ts +73 -41
  117. package/analyzer-template/project/writeMockDataTsx.ts +115 -54
  118. package/analyzer-template/project/writeScenarioComponents.ts +571 -162
  119. package/analyzer-template/project/writeSimpleRoot.ts +11 -13
  120. package/background/src/lib/virtualized/project/constructMockCode.js +265 -75
  121. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  122. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +67 -32
  123. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  124. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +5 -2
  125. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  126. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +11 -9
  127. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  128. package/background/src/lib/virtualized/project/serverOnlyModules.js +62 -25
  129. package/background/src/lib/virtualized/project/serverOnlyModules.js.map +1 -1
  130. package/background/src/lib/virtualized/project/start.js +6 -0
  131. package/background/src/lib/virtualized/project/start.js.map +1 -1
  132. package/background/src/lib/virtualized/project/startScenarioCapture.js +54 -31
  133. package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
  134. package/background/src/lib/virtualized/project/writeMockDataTsx.js +106 -46
  135. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  136. package/background/src/lib/virtualized/project/writeScenarioComponents.js +399 -106
  137. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  138. package/background/src/lib/virtualized/project/writeSimpleRoot.js +11 -11
  139. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  140. package/codeyam-cli/src/cli.js +2 -0
  141. package/codeyam-cli/src/cli.js.map +1 -1
  142. package/codeyam-cli/src/commands/debug.js +14 -2
  143. package/codeyam-cli/src/commands/debug.js.map +1 -1
  144. package/codeyam-cli/src/commands/recapture.js +215 -0
  145. package/codeyam-cli/src/commands/recapture.js.map +1 -0
  146. package/codeyam-cli/src/commands/report.js +26 -23
  147. package/codeyam-cli/src/commands/report.js.map +1 -1
  148. package/codeyam-cli/src/utils/backgroundServer.js +2 -2
  149. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  150. package/codeyam-cli/src/utils/generateReport.js +252 -106
  151. package/codeyam-cli/src/utils/generateReport.js.map +1 -1
  152. package/codeyam-cli/src/utils/install-skills.js +2 -2
  153. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  154. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js +38 -0
  155. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
  156. package/codeyam-cli/src/utils/queue/job.js +140 -16
  157. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  158. package/codeyam-cli/src/utils/queue/manager.js +19 -7
  159. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  160. package/codeyam-cli/src/utils/queue/persistence.js.map +1 -1
  161. package/codeyam-cli/src/webserver/app/lib/database.js +47 -0
  162. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  163. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  164. package/codeyam-cli/src/webserver/backgroundServer.js +5 -10
  165. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  166. package/codeyam-cli/src/webserver/bootstrap.js +9 -0
  167. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -0
  168. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-wXL1Z2Aq.js +1 -0
  169. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-efWKDYMr.js → EntityTypeBadge-CzGX-miz.js} +1 -1
  170. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-CXFKsCOD.js +41 -0
  171. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-D-9pXIaY.js +25 -0
  172. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-CBQPrpT0.js +3 -0
  173. package/codeyam-cli/src/webserver/build/client/assets/LoadingDots-D1CdlbrV.js +6 -0
  174. package/codeyam-cli/src/webserver/build/client/assets/LogViewer-wDPcZNKx.js +3 -0
  175. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-4lcOlid-.js +11 -0
  176. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BfmDgXxG.js +1 -0
  177. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-CUxUNEEC.js +15 -0
  178. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-COPstp9J.js → TruncatedFilePath-6J7zDUD5.js} +1 -1
  179. package/codeyam-cli/src/webserver/build/client/assets/_index-DHImXdXq.js +11 -0
  180. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CVP_WGQ3.js +32 -0
  181. package/codeyam-cli/src/webserver/build/client/assets/api.link-scenario-value-l0sNRNKZ.js +1 -0
  182. package/codeyam-cli/src/webserver/build/client/assets/api.update-key-attributes-l0sNRNKZ.js +1 -0
  183. package/codeyam-cli/src/webserver/build/client/assets/api.update-valid-values-l0sNRNKZ.js +1 -0
  184. package/codeyam-cli/src/webserver/build/client/assets/chevron-down-BYimnrHg.js +6 -0
  185. package/codeyam-cli/src/webserver/build/client/assets/chunk-JMJ3UQ3L-BambyYE_.js +51 -0
  186. package/codeyam-cli/src/webserver/build/client/assets/circle-check-CaVsIRxt.js +6 -0
  187. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CgUsG7ib.js +21 -0
  188. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-CKnwPCDr.js +1 -0
  189. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-DW_hdGUc.js +1 -0
  190. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-Dt-SjPsw.js +23 -0
  191. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DyB90fWk.js +1 -0
  192. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-D_3ero5o.js +1 -0
  193. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-CfLCUi9S.js +5 -0
  194. package/codeyam-cli/src/webserver/build/client/assets/entry.client-DKJyZfAY.js +29 -0
  195. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-DAtOlaWE.js +1 -0
  196. package/codeyam-cli/src/webserver/build/client/assets/files-ClR0d32A.js +1 -0
  197. package/codeyam-cli/src/webserver/build/client/assets/git-D62Lxxmv.js +15 -0
  198. package/codeyam-cli/src/webserver/build/client/assets/globals-C9s7Lhdl.css +1 -0
  199. package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-fmIEn3Bc.js +9 -0
  200. package/codeyam-cli/src/webserver/build/client/assets/index-BosqDOlH.js +3 -0
  201. package/codeyam-cli/src/webserver/build/client/assets/index-CzNNiTkw.js +9 -0
  202. package/codeyam-cli/src/webserver/build/client/assets/keyAttributeCoverage-CTlFMihX.js +1 -0
  203. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-CNp9QFCX.js +6 -0
  204. package/codeyam-cli/src/webserver/build/client/assets/manifest-0d27da29.js +1 -0
  205. package/codeyam-cli/src/webserver/build/client/assets/preload-helper-ckwbz45p.js +1 -0
  206. package/codeyam-cli/src/webserver/build/client/assets/root-B_wIKCIf.js +56 -0
  207. package/codeyam-cli/src/webserver/build/client/assets/scenarioStatus-B_8jpV3e.js +1 -0
  208. package/codeyam-cli/src/webserver/build/client/assets/search-DDGjYAMJ.js +6 -0
  209. package/codeyam-cli/src/webserver/build/client/assets/settings-DgTyB-Wg.js +1 -0
  210. package/codeyam-cli/src/webserver/build/client/assets/simulations-CoNWGt0K.js +1 -0
  211. package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-CBc5dE1s.js +6 -0
  212. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BMIGFP-m.js +1 -0
  213. package/codeyam-cli/src/webserver/build/client/assets/useInteractiveMode-Dk_FQqWJ.js +1 -0
  214. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-3pmpUQB-.js → useLastLogLine-BqPPNjAl.js} +1 -1
  215. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-DsJbgMY9.js +1 -0
  216. package/codeyam-cli/src/webserver/build/client/assets/{useToast-DEyawJ8r.js → useToast-DWHcCcl1.js} +1 -1
  217. package/codeyam-cli/src/webserver/build/server/assets/index-CU58-Ttc.js +1 -0
  218. package/codeyam-cli/src/webserver/build/server/assets/server-build-D35o2uae.js +175 -0
  219. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  220. package/codeyam-cli/src/webserver/build-info.json +5 -5
  221. package/codeyam-cli/src/webserver/devServer.js +1 -3
  222. package/codeyam-cli/src/webserver/devServer.js.map +1 -1
  223. package/codeyam-cli/templates/codeyam-setup-skill.md +138 -3
  224. package/codeyam-cli/templates/debug-codeyam.md +625 -0
  225. package/package.json +14 -14
  226. package/packages/ai/src/lib/analyzeScope.js +2 -0
  227. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  228. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +16 -0
  229. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  230. package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js +16 -0
  231. package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js.map +1 -1
  232. package/packages/ai/src/lib/astScopes/processExpression.js +305 -88
  233. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  234. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +582 -41
  235. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  236. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +2 -1
  237. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  238. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +454 -0
  239. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -0
  240. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +173 -55
  241. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  242. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +16 -1
  243. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  244. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +30 -1
  245. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  246. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +20 -0
  247. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  248. package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js +86 -0
  249. package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js.map +1 -0
  250. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +28 -2
  251. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  252. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +179 -17
  253. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +1 -1
  254. package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js +6 -0
  255. package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js.map +1 -1
  256. package/packages/ai/src/lib/generateChangesEntityScenarioData.js +41 -0
  257. package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
  258. package/packages/ai/src/lib/generateChangesEntityScenarios.js +37 -4
  259. package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
  260. package/packages/ai/src/lib/generateEntityDataStructure.js +4 -0
  261. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  262. package/packages/ai/src/lib/generateEntityKeyAttributes.js +176 -9
  263. package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +1 -1
  264. package/packages/ai/src/lib/generateEntityScenarioData.js +29 -25
  265. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  266. package/packages/ai/src/lib/generateEntityScenarios.js +105 -9
  267. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  268. package/packages/ai/src/lib/getConditionalUsagesFromCode.js +84 -14
  269. package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
  270. package/packages/ai/src/lib/guessScenarioDataFromDescription.js +2 -1
  271. package/packages/ai/src/lib/guessScenarioDataFromDescription.js.map +1 -1
  272. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +6 -0
  273. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  274. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +38 -2
  275. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
  276. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +38 -2
  277. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
  278. package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js +16 -3
  279. package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js.map +1 -1
  280. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  281. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +4 -0
  282. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  283. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +100 -23
  284. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  285. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +125 -0
  286. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -0
  287. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +298 -45
  288. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  289. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js +1 -1
  290. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js.map +1 -1
  291. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +201 -80
  292. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  293. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +10 -5
  294. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +1 -1
  295. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +55 -69
  296. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
  297. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +2 -5
  298. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
  299. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +171 -81
  300. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  301. package/packages/database/src/lib/kysely/db.js +2 -2
  302. package/packages/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
  303. package/packages/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
  304. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
  305. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  306. package/packages/generate/src/lib/deepMerge.js +27 -1
  307. package/packages/generate/src/lib/deepMerge.js.map +1 -1
  308. package/packages/types/index.js +1 -0
  309. package/packages/types/index.js.map +1 -1
  310. package/packages/types/src/types/Scenario.js +21 -1
  311. package/packages/types/src/types/Scenario.js.map +1 -1
  312. package/packages/utils/src/lib/lightweightEntityExtractor.js +25 -0
  313. package/packages/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  314. package/scripts/finalize-analyzer.cjs +3 -1
  315. package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js +0 -238
  316. package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js.map +0 -1
  317. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-CVbSvOjo.js +0 -1
  318. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-DcwcHyl5.js +0 -1
  319. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-WgwC1GfJ.js +0 -26
  320. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-IEKom9O2.js +0 -3
  321. package/codeyam-cli/src/webserver/build/client/assets/LogViewer-BYnfxbUG.js +0 -3
  322. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-_lBPJCzG.js +0 -1
  323. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-lHVhvsu_.js +0 -1
  324. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-d_TBk4GQ.js +0 -5
  325. package/codeyam-cli/src/webserver/build/client/assets/_index-kGT7VUqj.js +0 -1
  326. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-DDGmhu7P.js +0 -7
  327. package/codeyam-cli/src/webserver/build/client/assets/chevron-down-n_HPRfM_.js +0 -1
  328. package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-CbVoyx1U.js +0 -26
  329. package/codeyam-cli/src/webserver/build/client/assets/circle-check-D1VOYveA.js +0 -1
  330. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-YR8jjAlu.js +0 -1
  331. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-B8vP3V_s.js +0 -1
  332. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-CN6aLCT1.js +0 -16
  333. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DA5Jeu2P.js +0 -1
  334. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-BTeitalf.js +0 -5
  335. package/codeyam-cli/src/webserver/build/client/assets/entry.client-du6UEYD-.js +0 -13
  336. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-BpjkhMoi.js +0 -1
  337. package/codeyam-cli/src/webserver/build/client/assets/files-BQGvk4lJ.js +0 -1
  338. package/codeyam-cli/src/webserver/build/client/assets/git-DVdYRT-I.js +0 -12
  339. package/codeyam-cli/src/webserver/build/client/assets/globals-CO-U8Bpo.css +0 -1
  340. package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +0 -5
  341. package/codeyam-cli/src/webserver/build/client/assets/index-DCG-vks0.js +0 -1
  342. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-GazdNeLl.js +0 -1
  343. package/codeyam-cli/src/webserver/build/client/assets/manifest-0b694d28.js +0 -1
  344. package/codeyam-cli/src/webserver/build/client/assets/root-D3tQP7hx.js +0 -16
  345. package/codeyam-cli/src/webserver/build/client/assets/search-CIY6XmtE.js +0 -1
  346. package/codeyam-cli/src/webserver/build/client/assets/server-build-CMKNK2uU.css +0 -1
  347. package/codeyam-cli/src/webserver/build/client/assets/settings-CoMDgElu.js +0 -1
  348. package/codeyam-cli/src/webserver/build/client/assets/simulations-agkniXp2.js +0 -1
  349. package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-B2VUcygF.js +0 -1
  350. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-EvdK-zXP.js +0 -1
  351. package/codeyam-cli/src/webserver/build/server/assets/index-DGVHQEXD.js +0 -1
  352. package/codeyam-cli/src/webserver/build/server/assets/server-build-CghkTkIL.js +0 -166
  353. package/codeyam-cli/templates/debug-command.md +0 -303
  354. /package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CMKNK2uU.css → styles-CMKNK2uU.css} +0 -0
@@ -8,6 +8,51 @@ import * as fs from 'fs';
8
8
  import * as path from 'path';
9
9
  import ts from 'typescript';
10
10
  import { applyServerOnlyMocks } from "./serverOnlyModules.js";
11
+ // Debug timing helper for tracking where time is spent
12
+ const DEBUG_TIMING = process.env.DEBUG_WRITE_SCENARIO === 'true';
13
+ let debugStartTime;
14
+ let debugLastTime;
15
+ // Timeout protection to prevent infinite hangs
16
+ const WRITE_SCENARIO_TIMEOUT_MS = parseInt(process.env.WRITE_SCENARIO_TIMEOUT_MS || '300000', // Default 5 minutes
17
+ 10);
18
+ class WriteScenarioTimeoutError extends Error {
19
+ constructor(operation, timeoutMs) {
20
+ super(`WriteScenarioComponents timed out after ${timeoutMs}ms during: ${operation}`);
21
+ this.name = 'WriteScenarioTimeoutError';
22
+ }
23
+ }
24
+ async function withTimeout(operation, promise, timeoutMs = WRITE_SCENARIO_TIMEOUT_MS) {
25
+ let timeoutId;
26
+ const timeoutPromise = new Promise((_, reject) => {
27
+ timeoutId = setTimeout(() => {
28
+ reject(new WriteScenarioTimeoutError(operation, timeoutMs));
29
+ }, timeoutMs);
30
+ });
31
+ try {
32
+ return await Promise.race([promise, timeoutPromise]);
33
+ }
34
+ finally {
35
+ if (timeoutId)
36
+ clearTimeout(timeoutId);
37
+ }
38
+ }
39
+ function debugLog(message, extra) {
40
+ if (!DEBUG_TIMING)
41
+ return;
42
+ const now = Date.now();
43
+ if (!debugStartTime) {
44
+ debugStartTime = now;
45
+ debugLastTime = now;
46
+ }
47
+ const elapsed = now - debugStartTime;
48
+ const delta = now - debugLastTime;
49
+ debugLastTime = now;
50
+ console.log(`[WriteScenario +${elapsed}ms Δ${delta}ms] ${message}`, extra ? JSON.stringify(extra, null, 2) : '');
51
+ }
52
+ function resetDebugTiming() {
53
+ debugStartTime = 0;
54
+ debugLastTime = 0;
55
+ }
11
56
  /**
12
57
  * Find the end position of the last import/export-from statement using TypeScript AST.
13
58
  * This is more reliable than regex for handling multiline imports, comments, etc.
@@ -17,7 +62,10 @@ import { applyServerOnlyMocks } from "./serverOnlyModules.js";
17
62
  */
18
63
  function findEndOfImports(content) {
19
64
  try {
20
- const sourceFile = ts.createSourceFile('temp.ts', content, ts.ScriptTarget.Latest, true);
65
+ // Use temp.tsx to enable JSX parsing - otherwise TypeScript may misparse
66
+ // JSX content containing the word "import" (e.g., "Entities that import this")
67
+ // as an import statement, causing mock code to be inserted in the wrong location.
68
+ const sourceFile = ts.createSourceFile('temp.tsx', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
21
69
  let lastImportEnd = 0;
22
70
  // Visit all top-level statements to find import/export declarations
23
71
  for (const statement of sourceFile.statements) {
@@ -46,6 +94,106 @@ function findEndOfImports(content) {
46
94
  function escapeRegExp(str) {
47
95
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
48
96
  }
97
+ /**
98
+ * Remove a named import from file content using TypeScript AST.
99
+ * Handles both regular imports (`EntityName`) and type-only imports (`type EntityName`).
100
+ *
101
+ * @param fileContent - The file content to modify
102
+ * @param entityName - The name of the entity to remove from imports
103
+ * @returns The modified file content with the entity removed from imports
104
+ */
105
+ function removeNamedImportAst(fileContent, entityName) {
106
+ try {
107
+ const sourceFile = ts.createSourceFile('temp.tsx', fileContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
108
+ const replacements = [];
109
+ for (const statement of sourceFile.statements) {
110
+ if (!ts.isImportDeclaration(statement))
111
+ continue;
112
+ if (!statement.importClause?.namedBindings)
113
+ continue;
114
+ if (!ts.isNamedImports(statement.importClause.namedBindings))
115
+ continue;
116
+ const namedImports = statement.importClause.namedBindings;
117
+ const elements = namedImports.elements;
118
+ // Find the element that matches our entity name
119
+ const matchingIndex = elements.findIndex((el) => el.name.text === entityName);
120
+ if (matchingIndex === -1)
121
+ continue;
122
+ // Check if there's a default import (e.g., `import DefaultName, { NamedImport } from '...'`)
123
+ const hasDefaultImport = !!statement.importClause.name;
124
+ // If this is the only named import AND there's no default import, remove the entire statement
125
+ if (elements.length === 1 && !hasDefaultImport) {
126
+ // Find the end including any trailing newline
127
+ let end = statement.getEnd();
128
+ const afterStatement = fileContent.slice(end);
129
+ const trailingNewline = afterStatement.match(/^\r?\n/);
130
+ if (trailingNewline) {
131
+ end += trailingNewline[0].length;
132
+ }
133
+ replacements.push({
134
+ start: statement.getStart(sourceFile),
135
+ end,
136
+ replacement: '',
137
+ });
138
+ continue;
139
+ }
140
+ // Otherwise, rebuild the import without this element
141
+ const remainingElements = elements.filter((_, i) => i !== matchingIndex);
142
+ // Get the module specifier
143
+ const moduleSpecifier = statement.moduleSpecifier;
144
+ if (!ts.isStringLiteral(moduleSpecifier))
145
+ continue;
146
+ // Preserve import type modifier if present
147
+ const importTypePrefix = statement.importClause.isTypeOnly ? 'type ' : '';
148
+ // Get the default import name if present
149
+ const defaultImportName = statement.importClause.name?.text;
150
+ let newImport;
151
+ if (remainingElements.length === 0) {
152
+ // All named imports were removed, but there's a default import to preserve
153
+ // (we only get here when hasDefaultImport is true, because otherwise we'd have
154
+ // removed the whole statement at the elements.length === 1 check above)
155
+ newImport = `import ${defaultImportName} from ${moduleSpecifier.getText(sourceFile)};`;
156
+ }
157
+ else {
158
+ // Build the new named imports string
159
+ const newNamedImports = remainingElements
160
+ .map((el) => {
161
+ const isTypeOnly = el.isTypeOnly;
162
+ const name = el.name.text;
163
+ const propertyName = el.propertyName?.text;
164
+ if (propertyName) {
165
+ return isTypeOnly
166
+ ? `type ${propertyName} as ${name}`
167
+ : `${propertyName} as ${name}`;
168
+ }
169
+ return isTypeOnly ? `type ${name}` : name;
170
+ })
171
+ .join(', ');
172
+ // Build the new import statement, preserving default import if present
173
+ const defaultImportPrefix = defaultImportName
174
+ ? `${defaultImportName}, `
175
+ : '';
176
+ newImport = `import ${importTypePrefix}${defaultImportPrefix}{ ${newNamedImports} } from ${moduleSpecifier.getText(sourceFile)};`;
177
+ }
178
+ replacements.push({
179
+ start: statement.getStart(sourceFile),
180
+ end: statement.getEnd(),
181
+ replacement: newImport,
182
+ });
183
+ }
184
+ // Apply replacements in reverse order to preserve positions
185
+ let result = fileContent;
186
+ replacements.sort((a, b) => b.start - a.start);
187
+ for (const { start, end, replacement } of replacements) {
188
+ result = result.slice(0, start) + replacement + result.slice(end);
189
+ }
190
+ return result;
191
+ }
192
+ catch (error) {
193
+ console.warn('[removeNamedImportAst] Failed to parse file:', error);
194
+ return fileContent; // Return original content on error
195
+ }
196
+ }
49
197
  /**
50
198
  * Map nested dist paths to src paths.
51
199
  * Some build tools create nested structures like:
@@ -321,22 +469,37 @@ function stripServerOnlyImport(fileContent) {
321
469
  * Excludes node_modules imports (bare specifiers like 'react', '@prisma/client').
322
470
  */
323
471
  function extractInternalImportPaths(fileContent) {
472
+ // Always use AST parsing - regex with nested quantifiers can cause catastrophic
473
+ // backtracking that hangs on a single .exec() call (before iteration limits kick in)
474
+ return extractInternalImportPathsAst(fileContent);
475
+ }
476
+ /**
477
+ * Extract internal import paths using TypeScript AST - more reliable for large files
478
+ */
479
+ function extractInternalImportPathsAst(fileContent) {
324
480
  const importPaths = [];
325
- // Match import statements with their paths
326
- // Handles: import x from "path", import { x } from "path", import * as x from "path"
327
- const importRegex = /import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s*,?\s*)*\s*from\s*["']([^"']+)["']/g;
328
- let match;
329
- while ((match = importRegex.exec(fileContent)) !== null) {
330
- const importPath = match[1];
331
- // Skip node_modules imports (bare specifiers)
332
- // Internal imports start with '.', '@/', '~/' or similar path aliases
333
- if (importPath.startsWith('.') ||
334
- importPath.startsWith('@/') ||
335
- importPath.startsWith('~/') ||
336
- importPath.startsWith('#')) {
337
- importPaths.push(importPath);
481
+ try {
482
+ // Use temp.tsx to enable JSX parsing for consistent handling of JSX files
483
+ const sourceFile = ts.createSourceFile('temp.tsx', fileContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
484
+ for (const statement of sourceFile.statements) {
485
+ if (ts.isImportDeclaration(statement) && statement.moduleSpecifier) {
486
+ const moduleSpecifier = statement.moduleSpecifier;
487
+ if (ts.isStringLiteral(moduleSpecifier)) {
488
+ const importPath = moduleSpecifier.text;
489
+ // Skip node_modules imports (bare specifiers)
490
+ if (importPath.startsWith('.') ||
491
+ importPath.startsWith('@/') ||
492
+ importPath.startsWith('~/') ||
493
+ importPath.startsWith('#')) {
494
+ importPaths.push(importPath);
495
+ }
496
+ }
497
+ }
338
498
  }
339
499
  }
500
+ catch (error) {
501
+ console.warn('[extractInternalImportPathsAst] Failed to parse file:', error);
502
+ }
340
503
  return importPaths;
341
504
  }
342
505
  /**
@@ -441,8 +604,18 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
441
604
  const variableMockCodes = [];
442
605
  if (hasMultipleCallsWithVariables) {
443
606
  // Generate separate mock functions for each variable-qualified call
444
- // Track variable name occurrences to disambiguate when same variable is reused
445
- // (mirrors the logic in gatherDataForMocks)
607
+ // Look up canonical keys from dataForMocks and track variable names for function naming
608
+ // Get all call signature keys for this hook from dataForMocks
609
+ const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
610
+ // Match keys that start with the hook name (e.g., "useFetcher" matches "useFetcher<User>()")
611
+ const callSignatureKeysForHook = dataForMocks
612
+ ? Object.keys(dataForMocks).filter((key) => {
613
+ const hookBaseName = importedExport.name.split(/[<(]/)[0];
614
+ const keyBaseName = key.split(/[<(]/)[0];
615
+ return keyBaseName === hookBaseName;
616
+ })
617
+ : [];
618
+ // Track variable name occurrences for unique function naming
446
619
  const variableNameCounts = {};
447
620
  for (let i = 0; i < importedExport.calls.length; i++) {
448
621
  const variableName = importedExport.callVariableNames[i];
@@ -451,28 +624,31 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
451
624
  // Calculate the occurrence index for this variable name
452
625
  const occurrence = variableNameCounts[variableName] ?? 0;
453
626
  variableNameCounts[variableName] = occurrence + 1;
454
- // If this is a reused variable name (occurrence > 0), append index
455
- // e.g., "fetcher[1] <- useFetcher" for the second usage of "fetcher"
627
+ // Build indexed variable name for function naming
456
628
  const indexedVariableName = occurrence > 0 ? `${variableName}[${occurrence}]` : variableName;
457
- // Generate mock code for this specific call using variable-qualified name
458
- // Format: "variableName <- functionName" (reads as "variableName receives from functionName")
459
- const qualifiedName = `${indexedVariableName} <- ${importedExport.name}`;
460
- const variableMockCode = constructMockCode(qualifiedName, dependencySchemas, importedExport.entityType);
629
+ // Use safe function name with underscores instead of brackets
630
+ // e.g., fetcher[1] -> fetcher_1
631
+ const safeFunctionName = indexedVariableName.replace(/\[(\d+)\]/g, '_$1');
632
+ // Compute unique mock function name for call site replacement
633
+ // e.g., useFetcher_entityDiffFetcher, useFetcher_reportFetcher
634
+ const mockFunctionName = `${importedExport.name}_${safeFunctionName}`;
635
+ // Use the call signature from importedExport.calls[i] as the data key
636
+ // This matches what's stored in dataForMocks
637
+ const callSignature = importedExport.calls[i];
638
+ // Generate mock code using the call signature directly
639
+ // This prevents "symbol already declared" errors when multiple calls exist
640
+ const variableMockCode = constructMockCode(callSignature, // Use call signature format for data lookup
641
+ dependencySchemas, importedExport.entityType, undefined, // No need for separate canonical key
642
+ { uniqueFunctionSuffix: safeFunctionName });
461
643
  if (variableMockCode) {
462
644
  variableMockCodes.push(variableMockCode);
463
645
  // Replace the call site with the variable-specific mock function
464
646
  // e.g., useFetcher<BranchEntityDiffResult>() -> useFetcher_entityDiffFetcher()
465
647
  // e.g., useFetcher() -> useFetcher_reportFetcher()
466
- // For indexed variables: useFetcher() -> useFetcher_fetcher_1()
467
- const callSignature = importedExport.calls[i];
468
648
  // Escape special regex characters in the call signature
469
649
  const escapedCallSignature = callSignature.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
470
650
  // Create regex that matches the call (with optional whitespace variations)
471
651
  const callRegex = new RegExp(escapedCallSignature.replace(/\s+/g, '\\s*'), 'g');
472
- // Use safe function name with underscores instead of brackets
473
- // e.g., fetcher[1] -> fetcher_1
474
- const safeFunctionName = indexedVariableName.replace(/\[(\d+)\]/g, '_$1');
475
- const mockFunctionName = `${importedExport.name}_${safeFunctionName}`;
476
652
  fileContent = fileContent.replace(callRegex, `${mockFunctionName}()`);
477
653
  }
478
654
  }
@@ -487,15 +663,26 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
487
663
  ? importedExport.callVariableNames[0]
488
664
  : undefined;
489
665
  if (singleCallVariableName) {
490
- // For single variable assignments, use the variable-qualified key for data lookup
491
- // Use constructMockCode to generate proper dispatch functions for nested function calls
492
- // (e.g., useTranslation returns { t } where t() needs to dispatch based on translation key)
493
- const qualifiedKey = `${singleCallVariableName} <- ${importedExport.name}`;
494
- // Keep the original function name since there's only one call - no need for unique names
495
- mockCode = constructMockCode(qualifiedKey, dependencySchemas, importedExport.entityType, { keepOriginalFunctionName: true });
666
+ // For single variable assignments, use the call signature directly from dataForMocks
667
+ const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
668
+ // Find matching call signature key in dataForMocks
669
+ const hookBaseName = importedExport.name.split(/[<(]/)[0];
670
+ const callSignatureKey = dataForMocks
671
+ ? Object.keys(dataForMocks).find((key) => {
672
+ const keyBaseName = key.split(/[<(]/)[0];
673
+ return keyBaseName === hookBaseName;
674
+ })
675
+ : undefined;
676
+ // Use the call signature if found, otherwise construct it
677
+ const dataKey = callSignatureKey ??
678
+ importedExport.calls?.[0] ??
679
+ `${importedExport.name}()`;
680
+ // Keep the original function name since there's only one call
681
+ mockCode = constructMockCode(dataKey, // Use call signature format
682
+ dependencySchemas, importedExport.entityType, undefined, { keepOriginalFunctionName: true });
496
683
  // If constructMockCode didn't generate code, fall back to simple return
497
684
  if (!mockCode) {
498
- mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${qualifiedKey}"];
685
+ mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${dataKey}"];
499
686
 
500
687
  function ${importedExport.name}() {
501
688
  return ${importedExport.name}ReturnValue;
@@ -503,50 +690,38 @@ function ${importedExport.name}() {
503
690
  }
504
691
  }
505
692
  else {
506
- // Check if any analysis (fileAnalyses or rootAnalysis) has this function's data
507
- // under a variable-qualified key. The entity that CALLS the function (e.g., FileTableRow)
508
- // has the dataForMocks with the variable-qualified key, not the root analysis (e.g., GitView).
509
- let variableQualifiedKey;
510
- // First check fileAnalyses (the analyses for the entity being written)
511
- for (const analysis of fileAnalyses) {
512
- const dataForMocks = analysis.metadata?.scenariosDataStructure?.dataForMocks;
513
- if (dataForMocks) {
514
- variableQualifiedKey = Object.keys(dataForMocks).find((key) => {
515
- const match = key.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*<-\s*(.+)$/);
516
- return match && match[2] === importedExport.name;
517
- });
518
- if (variableQualifiedKey) {
693
+ // Helper to find matching call signature key from dataForMocks
694
+ const hookBaseName = importedExport.name.split(/[<(]/)[0];
695
+ const findMatchingKey = (dataForMocks) => {
696
+ if (!dataForMocks)
697
+ return undefined;
698
+ return Object.keys(dataForMocks).find((key) => {
699
+ const keyBaseName = key.split(/[<(]/)[0];
700
+ return keyBaseName === hookBaseName;
701
+ });
702
+ };
703
+ // Check rootAnalysis FIRST for matching keys.
704
+ // The mock DATA is generated from rootAnalysis, so the mock CODE must
705
+ // also use rootAnalysis keys to ensure the lookup succeeds.
706
+ let dataKey = findMatchingKey(rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks);
707
+ // If not found in rootAnalysis, fall back to fileAnalyses
708
+ if (!dataKey) {
709
+ for (const analysis of fileAnalyses) {
710
+ dataKey = findMatchingKey(analysis.metadata?.scenariosDataStructure?.dataForMocks);
711
+ if (dataKey)
519
712
  break;
520
- }
521
- }
522
- }
523
- // If not found in fileAnalyses, fall back to rootAnalysis
524
- if (!variableQualifiedKey) {
525
- const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
526
- if (dataForMocks) {
527
- variableQualifiedKey = Object.keys(dataForMocks).find((key) => {
528
- const match = key.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*<-\s*(.+)$/);
529
- return match && match[2] === importedExport.name;
530
- });
531
713
  }
532
714
  }
533
- if (variableQualifiedKey) {
534
- // Use the variable-qualified key found in the analysis
535
- // Use constructMockCode to generate proper dispatch functions for nested function calls
536
- // Keep the original function name since there's only one call - no need for unique names
537
- mockCode = constructMockCode(variableQualifiedKey, dependencySchemas, importedExport.entityType, { keepOriginalFunctionName: true });
538
- // If constructMockCode didn't generate code, fall back to simple return
539
- if (!mockCode) {
540
- mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${variableQualifiedKey}"];
715
+ // Use the data key if found, otherwise use call signature or function name
716
+ const mockNameToUse = dataKey ?? importedExport.calls?.[0] ?? `${importedExport.name}()`;
717
+ mockCode = constructMockCode(mockNameToUse, dependencySchemas, importedExport.entityType, undefined, { keepOriginalFunctionName: true });
718
+ // If constructMockCode didn't generate code, fall back to simple return
719
+ if (!mockCode && dataKey) {
720
+ mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${dataKey}"];
541
721
 
542
722
  function ${importedExport.name}() {
543
723
  return ${importedExport.name}ReturnValue;
544
724
  }`;
545
- }
546
- }
547
- else {
548
- // Original behavior for calls without variable names
549
- mockCode = constructMockCode(importedExport.name, dependencySchemas, importedExport.entityType);
550
725
  }
551
726
  }
552
727
  }
@@ -764,6 +939,14 @@ function captureArgumentsForTesting(args) {
764
939
  }
765
940
  export default async function writeScenarioComponents({ project, file, entity, rootAnalysis, scenario, context, projectAnalyzer, framework, mocksDir, rootFile, namespaceMocks, writtenScenarioComponents = {}, fileStore, exportAsNamed, }) {
766
941
  var _a;
942
+ // Reset debug timing for this invocation
943
+ resetDebugTiming();
944
+ debugLog('START writeScenarioComponents', {
945
+ filePath: file.path,
946
+ entityName: entity.name,
947
+ scenarioName: scenario.name,
948
+ isRootFile: !rootFile || rootFile === file,
949
+ });
767
950
  // Capture arguments for testing if debug mode is enabled
768
951
  captureArgumentsForTesting({
769
952
  project,
@@ -907,7 +1090,20 @@ export default async function writeScenarioComponents({ project, file, entity, r
907
1090
  return 1;
908
1091
  return 0;
909
1092
  });
1093
+ debugLog('Starting main importedExports loop', {
1094
+ count: sortedImportedExports.length,
1095
+ fileContentLength: fileContent.length,
1096
+ });
1097
+ let importedExportIndex = 0;
910
1098
  for (const importedExport of sortedImportedExports) {
1099
+ importedExportIndex++;
1100
+ if (importedExportIndex % 5 === 0 || importedExportIndex === 1) {
1101
+ debugLog(`Processing importedExport ${importedExportIndex}/${sortedImportedExports.length}`, {
1102
+ name: importedExport.name,
1103
+ filePath: importedExport.filePath,
1104
+ isMocked: importedExport.isMocked,
1105
+ });
1106
+ }
911
1107
  // IMPORTANT: The import mapping keys may be either absolute or relative paths
912
1108
  // depending on how they were created by the file analyzer. We try multiple formats.
913
1109
  // Also need to normalize paths to handle /tmp vs /private/tmp on macOS
@@ -1034,7 +1230,11 @@ export default async function writeScenarioComponents({ project, file, entity, r
1034
1230
  // e.g., if file has `export default X` but parent does `import { X } from '...'`
1035
1231
  const needsNamedReExport = importedExport.resolvedIsDefault === true &&
1036
1232
  importedExport.isDefault === false;
1037
- const { scenarioComponentPaths: newScenarioComponentPaths, writtenScenarioComponents: updatedWrittenScenarioComponents, } = await writeScenarioComponents({
1233
+ debugLog(`Recursing into writeScenarioComponents for ${importedExportEntity.name}`, {
1234
+ entityName: importedExportEntity.name,
1235
+ filePath: fileNotMocked.path,
1236
+ });
1237
+ const { scenarioComponentPaths: newScenarioComponentPaths, writtenScenarioComponents: updatedWrittenScenarioComponents, } = await withTimeout(`recursive writeScenarioComponents for ${importedExportEntity.name}`, writeScenarioComponents({
1038
1238
  project,
1039
1239
  file: fileNotMocked,
1040
1240
  entity: importedExportEntity,
@@ -1052,7 +1252,8 @@ export default async function writeScenarioComponents({ project, file, entity, r
1052
1252
  exportAsNamed: needsNamedReExport
1053
1253
  ? importedExport.name
1054
1254
  : undefined,
1055
- });
1255
+ }), 60000);
1256
+ debugLog(`Completed recursive writeScenarioComponents for ${importedExportEntity.name}`);
1056
1257
  writtenScenarioComponents = updatedWrittenScenarioComponents;
1057
1258
  scenarioComponentPaths.push(...newScenarioComponentPaths);
1058
1259
  }
@@ -1286,9 +1487,7 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1286
1487
  : `import { ${entityImportName} } from '${path}';`;
1287
1488
  // First, try to remove this entity from the already-rewritten grouped import
1288
1489
  // This prevents duplicate/conflicting imports
1289
- // IMPORTANT: Only remove from import statements, NOT from the entire file!
1290
- // The global patterns used previously would also match type annotations like:
1291
- // "param: MyType," in function signatures, corrupting the syntax.
1490
+ // Use AST-based removal to properly handle type-only imports like `type EntityName`
1292
1491
  const escapedEntityName = escapeRegExp(entityImportName);
1293
1492
  // For default imports: remove "DefaultName, " from "import DefaultName, { ... }"
1294
1493
  // This handles the case where a default export is being split out
@@ -1296,27 +1495,12 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1296
1495
  const defaultImportPattern = new RegExp(`(import\\s+)${escapedEntityName}\\s*,\\s*(\\{)`, 'gm');
1297
1496
  fileContent = fileContent.replace(defaultImportPattern, '$1$2');
1298
1497
  }
1299
- // Match import statements that contain this entity and remove just the entity
1300
- // Pattern: import { ... EntityName, ... } from '...'
1301
- // We match the full import and use a replacer function to remove the entity name
1302
- const importWithEntityPattern = new RegExp(`(import\\s*\\{)([^}]*\\b${escapedEntityName}\\b[^}]*)(\\}\\s*from\\s*['"][^'"]*['"];?)`, 'gm');
1303
- fileContent = fileContent.replace(importWithEntityPattern, (match, prefix, namedImports, suffix) => {
1304
- // Remove the entity name from the named imports
1305
- let cleaned = namedImports
1306
- .replace(new RegExp(`\\b${escapedEntityName}\\s*,\\s*`), '') // "EntityName, "
1307
- .replace(new RegExp(`\\s*,\\s*${escapedEntityName}\\b`), '') // ", EntityName"
1308
- .replace(new RegExp(`\\b${escapedEntityName}\\b`), ''); // "EntityName" (only one)
1309
- // Clean up any double commas or leading/trailing commas
1310
- cleaned = cleaned
1311
- .replace(/,\s*,/g, ',')
1312
- .replace(/^\s*,\s*/, '')
1313
- .replace(/\s*,\s*$/, '');
1314
- // If no imports left, remove the entire import statement
1315
- if (cleaned.trim() === '') {
1316
- return '';
1317
- }
1318
- return prefix + cleaned + suffix;
1319
- });
1498
+ // Remove the named import using AST parsing
1499
+ // This properly handles:
1500
+ // - Regular imports: `import { EntityName } from '...'`
1501
+ // - Type-only imports: `import { type EntityName } from '...'`
1502
+ // - Mixed imports: `import { type EntityName, OtherName } from '...'`
1503
+ fileContent = removeNamedImportAst(fileContent, entityImportName);
1320
1504
  // Add the new import at the beginning of fileContent
1321
1505
  // Note: The header comment (// Scenario:) doesn't exist yet - it's prepended at writeFile time
1322
1506
  // So prepending here puts the import right after the header in the final output
@@ -1330,17 +1514,27 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1330
1514
  }
1331
1515
  }
1332
1516
  }
1517
+ // Collect universal mocks BEFORE processing nodeModuleImports
1518
+ // This is needed to check if a node module import is handled by a universal mock
1519
+ const universalMocks = project.metadata?.universalMocks ?? [];
1520
+ const nodeModuleUniversalMocks = universalMocks.filter((mock) => mock.nodeModule && mock.content);
1521
+ // Create a set of import paths that have universal mocks for quick lookup
1522
+ const universalMockPaths = new Set(nodeModuleUniversalMocks.map((mock) => mock.filePath));
1333
1523
  for (const nodeModuleImport of nodeModuleImports) {
1334
1524
  if (!nodeModuleImport.isMocked)
1335
1525
  continue;
1526
+ // Skip generating local mock functions for imports that have universal mocks.
1527
+ // Universal mocks provide the exports via rewritten import paths (handled below).
1528
+ // Generating a local mock function would cause "name defined multiple times" errors.
1529
+ if (universalMockPaths.has(nodeModuleImport.filePath)) {
1530
+ continue;
1531
+ }
1336
1532
  fileContent = addMockToContent(fileContent, nodeModuleImport, fileAnalyses, rootAnalysis, relativeMocksDir, scenario.name, importMapping[nodeModuleImport.filePath] ?? nodeModuleImport.filePath);
1337
1533
  }
1338
1534
  // Rewrite node_module imports that have universal mocks
1339
1535
  // Universal mocks create mock files at __codeyamMocks__/{safeFileName}.tsx
1340
1536
  // We need to rewrite imports like `import { logger } from "@formbricks/logger"`
1341
1537
  // to `import { logger } from "../__codeyamMocks__/_formbricks_logger.js"`
1342
- const universalMocks = project.metadata?.universalMocks ?? [];
1343
- const nodeModuleUniversalMocks = universalMocks.filter((mock) => mock.nodeModule && mock.content);
1344
1538
  for (const universalMock of nodeModuleUniversalMocks) {
1345
1539
  const originalPath = universalMock.filePath;
1346
1540
  // Create the mock file name using the same safeFileName function as writeUniversalMocks
@@ -1388,20 +1582,30 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1388
1582
  scenario,
1389
1583
  });
1390
1584
  }
1585
+ debugLog('Route path computed', { scenarioComponentPath });
1391
1586
  // Strip <html> and <body> tags from root layout files for Next.js
1392
1587
  // These tags cause hydration errors when the scenario layout is nested under the real root
1588
+ debugLog('Starting stripHtmlBodyTags');
1393
1589
  fileContent = stripHtmlBodyTags(fileContent, file.path, framework);
1590
+ debugLog('Completed stripHtmlBodyTags');
1394
1591
  // Strip "server-only" imports for Next.js
1395
1592
  // These cause errors when the scenario component is rendered client-side
1593
+ debugLog('Starting stripServerOnlyImport');
1396
1594
  fileContent = stripServerOnlyImport(fileContent);
1595
+ debugLog('Starting applyServerOnlyMocks');
1397
1596
  fileContent = applyServerOnlyMocks(fileContent);
1597
+ debugLog('Completed server-only processing');
1398
1598
  // Rewrite asset imports (CSS, images, fonts, etc.) to correct relative paths
1399
1599
  // The original file path is relative to PROJECT_RELATIVE_PATH, the new path is scenarioComponentPath
1600
+ debugLog('Starting rewriteAssetImports');
1400
1601
  fileContent = rewriteAssetImports(fileContent, `${PROJECT_RELATIVE_PATH}/${file.path}`, scenarioComponentPath);
1602
+ debugLog('Completed rewriteAssetImports');
1401
1603
  // Rewrite relative TypeScript/JavaScript module imports to correct relative paths
1402
1604
  // This handles cases where the file is moved (e.g., from [environmentId]/ to _environmentId_/)
1403
1605
  // and relative imports like "./lib/organization" need to be rewritten
1606
+ debugLog('Starting rewriteRelativeModuleImports');
1404
1607
  fileContent = rewriteRelativeModuleImports(fileContent, `${PROJECT_RELATIVE_PATH}/${file.path}`, scenarioComponentPath);
1608
+ debugLog('Completed rewriteRelativeModuleImports');
1405
1609
  /**
1406
1610
  * Recursively process a file's imports to create transitive copies with server-only stripped.
1407
1611
  * This handles chains of arbitrary depth: A -> B -> C -> D where each needs server-only removed.
@@ -1413,16 +1617,44 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1413
1617
  * @param visitedPaths - Set of file paths currently being processed (for cycle detection)
1414
1618
  * @returns The modified content with imports rewritten to point to transitive copies
1415
1619
  */
1416
- async function processTransitiveImportsRecursively(content, sourceFilePath, targetFilePath, visitedPaths = new Set()) {
1620
+ async function processTransitiveImportsRecursively(content, sourceFilePath, targetFilePath, visitedPaths = new Set(), depth = 0, startTime = Date.now()) {
1621
+ // Global timeout for entire transitive processing
1622
+ const GLOBAL_TIMEOUT_MS = 60000; // 1 minute max for all transitive processing
1623
+ const elapsed = Date.now() - startTime;
1624
+ if (elapsed > GLOBAL_TIMEOUT_MS) {
1625
+ throw new Error(`processTransitiveImportsRecursively exceeded ${GLOBAL_TIMEOUT_MS}ms (elapsed: ${elapsed}ms) at depth=${depth} for ${sourceFilePath}`);
1626
+ }
1417
1627
  const importPaths = extractInternalImportPaths(content);
1628
+ debugLog(`processTransitiveImportsRecursively depth=${depth}`, {
1629
+ sourceFilePath,
1630
+ importCount: importPaths.length,
1631
+ visitedCount: visitedPaths.size,
1632
+ });
1418
1633
  let modifiedContent = content;
1419
- for (const importPath of importPaths) {
1634
+ // Safety check: limit iterations to prevent infinite loops
1635
+ const MAX_IMPORTS_PER_FILE = 100;
1636
+ if (importPaths.length > MAX_IMPORTS_PER_FILE) {
1637
+ console.warn(`[WriteScenario] WARNING: File ${sourceFilePath} has ${importPaths.length} imports (> ${MAX_IMPORTS_PER_FILE}), limiting processing`);
1638
+ }
1639
+ let importIndex = 0;
1640
+ debugLog(`Starting import loop at depth=${depth}, ${importPaths.length} imports to process`);
1641
+ const slicedImports = importPaths.slice(0, MAX_IMPORTS_PER_FILE);
1642
+ for (const importPath of slicedImports) {
1643
+ if (!importPath) {
1644
+ continue;
1645
+ }
1646
+ importIndex++;
1647
+ debugLog(`[LOOP] depth=${depth} import ${importIndex}/${Math.min(importPaths.length, MAX_IMPORTS_PER_FILE)}: ${importPath}`);
1648
+ debugLog(`[LOOP] Calling resolveImportPath...`);
1420
1649
  const resolvedPath = resolveImportPath(importPath, sourceFilePath, project);
1650
+ debugLog(`[LOOP] resolveImportPath returned: ${resolvedPath?.slice(0, 80) ?? 'null'}`);
1421
1651
  if (!resolvedPath)
1422
1652
  continue;
1653
+ debugLog(`[LOOP] Looking up importFile...`);
1423
1654
  let importFile = fileStore
1424
1655
  ? fileStore.getByPath(resolvedPath)
1425
1656
  : project.files?.find((f) => f.path === resolvedPath);
1657
+ debugLog(`[LOOP] importFile lookup result: ${importFile ? 'found' : 'not found'}`);
1426
1658
  if (!importFile)
1427
1659
  continue;
1428
1660
  // Build the transitive file path (needed for import rewriting even if we skip creating)
@@ -1450,8 +1682,17 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1450
1682
  // Strip server-only and mock server-only packages, then recursively process imports
1451
1683
  let transitiveContent = stripServerOnlyImport(importFile.content);
1452
1684
  transitiveContent = applyServerOnlyMocks(transitiveContent);
1453
- transitiveContent = await processTransitiveImportsRecursively(transitiveContent, importFile.path, transitiveFilePath, visitedPaths);
1685
+ debugLog(`processTransitiveImportsRecursively depth=${depth} for ${importFile.path}`);
1686
+ debugLog(`Calling processTransitiveImportsRecursively depth=${depth + 1} for ${importFile.path}`);
1687
+ transitiveContent = await withTimeout(`processTransitiveImportsRecursively depth=${depth} for ${path.basename(importFile.path)}`, processTransitiveImportsRecursively(transitiveContent, importFile.path, transitiveFilePath, visitedPaths, depth + 1, startTime), 30000);
1688
+ debugLog(`withTimeout returned for depth=${depth}, transitiveContent length=${transitiveContent.length}`);
1689
+ debugLog(`Completed processTransitiveImportsRecursively depth=${depth} for ${importFile.path}`);
1690
+ debugLog(`Writing transitive file depth=${depth}`, {
1691
+ transitiveFilePath: path.basename(transitiveFilePath),
1692
+ contentLength: transitiveContent.length,
1693
+ });
1454
1694
  await writeFile(transitiveFilePath, transitiveContent);
1695
+ debugLog(`Wrote transitive file depth=${depth}`);
1455
1696
  scenarioComponentPaths.push(transitiveFilePath);
1456
1697
  if (!writtenScenarioComponents[resolvedPath]) {
1457
1698
  writtenScenarioComponents[resolvedPath] = [];
@@ -1461,22 +1702,63 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1461
1702
  }
1462
1703
  // ALWAYS rewrite the import to point to the transitive copy
1463
1704
  // (even for circular imports or already-processed files)
1705
+ debugLog(`Rewriting import path depth=${depth}`, {
1706
+ importPath,
1707
+ resolvedPath,
1708
+ });
1464
1709
  const relativePath = getRelativePath(targetFilePath, transitiveFilePath);
1465
1710
  const relativePathWithoutExt = relativePath.replace(/\.(ts|tsx|js|jsx)$/, '');
1466
1711
  const safeRelativePath = safeFolder(relativePathWithoutExt);
1467
1712
  const escapedImportPath = importPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1468
- const importRegex = new RegExp(`(from\\s*["'])${escapedImportPath}(["'])`, 'g');
1469
- modifiedContent = modifiedContent.replace(importRegex, `$1${safeRelativePath}$2`);
1713
+ debugLog(`Applying regex depth=${depth}`, {
1714
+ escapedImportPath,
1715
+ contentLength: modifiedContent.length,
1716
+ });
1717
+ // Quick check if the import path even exists in content
1718
+ const simpleCheck = modifiedContent.includes(importPath);
1719
+ debugLog(`Simple check: importPath "${importPath}" exists: ${simpleCheck}`);
1720
+ if (!simpleCheck) {
1721
+ debugLog(`Skipping regex - import path not found in content`);
1722
+ }
1723
+ else {
1724
+ const regexPattern = `(from\\s*["'])${escapedImportPath}(["'])`;
1725
+ debugLog(`Regex pattern: ${regexPattern.slice(0, 100)}`);
1726
+ const importRegex = new RegExp(regexPattern, 'g');
1727
+ debugLog(`About to call replace...`);
1728
+ // Timing for regex replace to detect slow operations
1729
+ const replaceStart = Date.now();
1730
+ modifiedContent = modifiedContent.replace(importRegex, `$1${safeRelativePath}$2`);
1731
+ const replaceTime = Date.now() - replaceStart;
1732
+ if (replaceTime > 100) {
1733
+ console.warn(`[WriteScenario] SLOW regex replace: ${replaceTime}ms for pattern ${regexPattern.slice(0, 50)} on ${modifiedContent.length} bytes`);
1734
+ }
1735
+ debugLog(`Regex applied depth=${depth} in ${replaceTime}ms`);
1736
+ }
1737
+ debugLog(`[LOOP END] depth=${depth} import ${importIndex} completed`);
1470
1738
  }
1739
+ debugLog(`[LOOP DONE] Exiting import loop at depth=${depth}`);
1740
+ debugLog(`Returning from processTransitiveImportsRecursively depth=${depth}`);
1471
1741
  return modifiedContent;
1472
1742
  }
1473
1743
  // Process remaining internal imports that weren't in importedExports
1474
1744
  // This handles transitive dependencies: when the file content includes code (e.g., from
1475
1745
  // other functions in the same file) that imports from files with "server-only"
1746
+ debugLog('Extracting remaining import paths');
1476
1747
  const remainingImportPaths = extractInternalImportPaths(fileContent);
1748
+ debugLog('Found remaining import paths', {
1749
+ count: remainingImportPaths.length,
1750
+ });
1477
1751
  // Get all file paths that are in importedExports - these are handled by main processing
1478
1752
  const importedExportFilePaths = new Set(allImportedExports.map((ie) => ie.resolvedFilePath || ie.filePath));
1753
+ debugLog('Starting remaining imports loop', {
1754
+ remainingCount: remainingImportPaths.length,
1755
+ importedExportCount: importedExportFilePaths.size,
1756
+ });
1757
+ let remainingImportIndex = 0;
1758
+ debugLog(`[REMAINING] Starting remaining imports loop, ${remainingImportPaths.length} imports`);
1479
1759
  for (const importPath of remainingImportPaths) {
1760
+ remainingImportIndex++;
1761
+ debugLog(`[REMAINING LOOP] import ${remainingImportIndex}/${remainingImportPaths.length}: ${importPath}`);
1480
1762
  // Resolve the import path to a project file path
1481
1763
  const resolvedFilePath = resolveImportPath(importPath, file.path, project);
1482
1764
  if (!resolvedFilePath) {
@@ -1537,7 +1819,11 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1537
1819
  // Recursively process this transitive file's imports
1538
1820
  // This handles the nested case: service.ts → brevo.ts → constants.ts
1539
1821
  const nestedImportPaths = extractInternalImportPaths(transformedContent);
1822
+ debugLog(`[NESTED] Processing ${nestedImportPaths.length} nested imports for ${targetFile.path}`);
1823
+ let nestedIndex = 0;
1540
1824
  for (const nestedImportPath of nestedImportPaths) {
1825
+ nestedIndex++;
1826
+ debugLog(`[NESTED LOOP] import ${nestedIndex}/${nestedImportPaths.length}: ${nestedImportPath}`);
1541
1827
  const nestedResolvedPath = resolveImportPath(nestedImportPath, targetFile.path, project);
1542
1828
  if (!nestedResolvedPath)
1543
1829
  continue;
@@ -1568,7 +1854,9 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1568
1854
  // This handles chains of any depth: A -> B -> C -> D
1569
1855
  let nestedContent = stripServerOnlyImport(nestedFile.content);
1570
1856
  nestedContent = applyServerOnlyMocks(nestedContent);
1571
- nestedContent = await processTransitiveImportsRecursively(nestedContent, nestedFile.path, nestedTransformedPath);
1857
+ debugLog(`processTransitiveImportsRecursively (nested) for ${nestedFile.path}`);
1858
+ nestedContent = await withTimeout(`processTransitiveImportsRecursively (nested) for ${path.basename(nestedFile.path)}`, processTransitiveImportsRecursively(nestedContent, nestedFile.path, nestedTransformedPath), 30000);
1859
+ debugLog(`Completed processTransitiveImportsRecursively (nested) for ${nestedFile.path}`);
1572
1860
  await writeFile(nestedTransformedPath, nestedContent);
1573
1861
  scenarioComponentPaths.push(nestedTransformedPath);
1574
1862
  // Mark as written
@@ -1639,7 +1927,12 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
1639
1927
  else {
1640
1928
  finalContent = `${scenarioComponentComment}\n\n${fileContent}`;
1641
1929
  }
1930
+ debugLog('About to write final scenario file', {
1931
+ scenarioComponentPath,
1932
+ contentLength: finalContent.length,
1933
+ });
1642
1934
  await writeFile(scenarioComponentPath, finalContent);
1935
+ debugLog('Successfully wrote scenario file');
1643
1936
  scenarioComponentPaths.push(scenarioComponentPath);
1644
1937
  return { scenarioComponentPaths, writtenScenarioComponents };
1645
1938
  }