@codeyam/codeyam-cli 0.1.0-staging.415103 → 0.1.0-staging.435c1ad

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 (623) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +11 -11
  4. package/analyzer-template/packages/ai/package.json +2 -2
  5. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
  8. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +36 -9
  9. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
  10. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
  11. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +0 -33
  12. package/analyzer-template/packages/analyze/index.ts +4 -1
  13. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +13 -7
  14. package/analyzer-template/packages/analyze/src/lib/asts/index.ts +7 -2
  15. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
  16. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
  17. package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +10 -6
  18. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +9 -12
  19. package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
  20. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
  21. package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +4 -0
  22. package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +4 -0
  23. package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
  24. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +239 -58
  25. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +0 -98
  26. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1684 -1462
  27. package/analyzer-template/packages/aws/package.json +2 -2
  28. package/analyzer-template/packages/database/package.json +4 -4
  29. package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +102 -0
  30. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +25 -15
  31. package/analyzer-template/packages/database/src/lib/loadEntities.ts +0 -6
  32. package/analyzer-template/packages/database/src/lib/loadEntity.ts +19 -8
  33. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +0 -65
  34. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +9 -0
  35. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -1
  36. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +104 -0
  37. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  38. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  39. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
  40. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  41. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  42. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +0 -6
  43. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  44. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts +4 -1
  45. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts.map +1 -1
  46. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js +5 -5
  47. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js.map +1 -1
  48. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  49. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +0 -25
  50. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  51. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts +2 -0
  52. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
  53. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js +2 -0
  54. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js.map +1 -1
  55. package/analyzer-template/packages/github/package.json +1 -1
  56. package/analyzer-template/packages/types/src/enums/ProjectFramework.ts +2 -0
  57. package/analyzer-template/packages/ui-components/package.json +1 -1
  58. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts +2 -0
  59. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
  60. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js +2 -0
  61. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js.map +1 -1
  62. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts +3 -1
  63. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  64. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +22 -1
  65. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  66. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +27 -0
  67. package/analyzer-template/project/analyzeFileEntities.ts +26 -0
  68. package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
  69. package/background/src/lib/virtualized/project/analyzeFileEntities.js +22 -0
  70. package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
  71. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
  72. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  73. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js +196 -0
  74. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js.map +1 -0
  75. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js +114 -0
  76. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js.map +1 -0
  77. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js +149 -0
  78. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js.map +1 -0
  79. package/codeyam-cli/src/cli.js +24 -0
  80. package/codeyam-cli/src/cli.js.map +1 -1
  81. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
  82. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
  83. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +71 -0
  84. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
  85. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
  86. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
  87. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js +51 -0
  88. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js.map +1 -0
  89. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +56 -0
  90. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
  91. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +101 -47
  92. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
  93. package/codeyam-cli/src/commands/default.js +3 -46
  94. package/codeyam-cli/src/commands/default.js.map +1 -1
  95. package/codeyam-cli/src/commands/editor.js +5366 -356
  96. package/codeyam-cli/src/commands/editor.js.map +1 -1
  97. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
  98. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
  99. package/codeyam-cli/src/commands/editorIsolateArgs.js +25 -0
  100. package/codeyam-cli/src/commands/editorIsolateArgs.js.map +1 -0
  101. package/codeyam-cli/src/commands/init.js +75 -35
  102. package/codeyam-cli/src/commands/init.js.map +1 -1
  103. package/codeyam-cli/src/commands/telemetry.js +37 -0
  104. package/codeyam-cli/src/commands/telemetry.js.map +1 -0
  105. package/codeyam-cli/src/data/designSystems.js +27 -0
  106. package/codeyam-cli/src/data/designSystems.js.map +1 -0
  107. package/codeyam-cli/src/data/techStacks.js +77 -0
  108. package/codeyam-cli/src/data/techStacks.js.map +1 -0
  109. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +173 -0
  110. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
  111. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js +46 -0
  112. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js.map +1 -0
  113. package/codeyam-cli/src/utils/__tests__/devServerState.test.js +134 -0
  114. package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -0
  115. package/codeyam-cli/src/utils/__tests__/editorApi.test.js +181 -0
  116. package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -0
  117. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +4014 -0
  118. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -0
  119. package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js +76 -0
  120. package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js.map +1 -0
  121. package/codeyam-cli/src/utils/__tests__/editorCapture.test.js +93 -0
  122. package/codeyam-cli/src/utils/__tests__/editorCapture.test.js.map +1 -0
  123. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
  124. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
  125. package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js +100 -0
  126. package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js.map +1 -0
  127. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js +304 -0
  128. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js.map +1 -0
  129. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +194 -0
  130. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -0
  131. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +381 -0
  132. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -0
  133. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js +67 -0
  134. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js.map +1 -0
  135. package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js +294 -0
  136. package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js.map +1 -0
  137. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js +542 -0
  138. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js.map +1 -0
  139. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js +594 -0
  140. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js.map +1 -0
  141. package/codeyam-cli/src/utils/__tests__/editorMigration.test.js +435 -0
  142. package/codeyam-cli/src/utils/__tests__/editorMigration.test.js.map +1 -0
  143. package/codeyam-cli/src/utils/__tests__/editorMockState.test.js +270 -0
  144. package/codeyam-cli/src/utils/__tests__/editorMockState.test.js.map +1 -0
  145. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js +217 -0
  146. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js.map +1 -0
  147. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +361 -0
  148. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -0
  149. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +153 -0
  150. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -0
  151. package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js +139 -0
  152. package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js.map +1 -0
  153. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +291 -0
  154. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -0
  155. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +1768 -0
  156. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -0
  157. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +329 -0
  158. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -0
  159. package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js +143 -0
  160. package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js.map +1 -0
  161. package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js +66 -0
  162. package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js.map +1 -0
  163. package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js +53 -0
  164. package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js.map +1 -0
  165. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +2121 -0
  166. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -0
  167. package/codeyam-cli/src/utils/__tests__/git.editor.test.js +134 -0
  168. package/codeyam-cli/src/utils/__tests__/git.editor.test.js.map +1 -0
  169. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
  170. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
  171. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +122 -0
  172. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -0
  173. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
  174. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
  175. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js +129 -0
  176. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js.map +1 -0
  177. package/codeyam-cli/src/utils/__tests__/project.test.js +65 -0
  178. package/codeyam-cli/src/utils/__tests__/project.test.js.map +1 -0
  179. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js +127 -0
  180. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js.map +1 -0
  181. package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js +118 -0
  182. package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js.map +1 -0
  183. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +284 -0
  184. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -0
  185. package/codeyam-cli/src/utils/__tests__/scenarioMarkers.test.js +121 -0
  186. package/codeyam-cli/src/utils/__tests__/scenarioMarkers.test.js.map +1 -0
  187. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +672 -0
  188. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -0
  189. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js +84 -0
  190. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js.map +1 -0
  191. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +26 -5
  192. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  193. package/codeyam-cli/src/utils/__tests__/telemetry.test.js +159 -0
  194. package/codeyam-cli/src/utils/__tests__/telemetry.test.js.map +1 -0
  195. package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js +51 -0
  196. package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js.map +1 -0
  197. package/codeyam-cli/src/utils/__tests__/testRunner.test.js +217 -0
  198. package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
  199. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +142 -0
  200. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -0
  201. package/codeyam-cli/src/utils/analysisRunner.js +39 -8
  202. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  203. package/codeyam-cli/src/utils/analyzer.js +19 -0
  204. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  205. package/codeyam-cli/src/utils/analyzerFinalization.js +100 -0
  206. package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
  207. package/codeyam-cli/src/utils/backgroundServer.js +95 -19
  208. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  209. package/codeyam-cli/src/utils/buildFlags.js +4 -0
  210. package/codeyam-cli/src/utils/buildFlags.js.map +1 -0
  211. package/codeyam-cli/src/utils/database.js +37 -2
  212. package/codeyam-cli/src/utils/database.js.map +1 -1
  213. package/codeyam-cli/src/utils/devServerState.js +71 -0
  214. package/codeyam-cli/src/utils/devServerState.js.map +1 -0
  215. package/codeyam-cli/src/utils/editorApi.js +95 -0
  216. package/codeyam-cli/src/utils/editorApi.js.map +1 -0
  217. package/codeyam-cli/src/utils/editorAudit.js +827 -0
  218. package/codeyam-cli/src/utils/editorAudit.js.map +1 -0
  219. package/codeyam-cli/src/utils/editorBroadcastViewport.js +26 -0
  220. package/codeyam-cli/src/utils/editorBroadcastViewport.js.map +1 -0
  221. package/codeyam-cli/src/utils/editorCapture.js +102 -0
  222. package/codeyam-cli/src/utils/editorCapture.js.map +1 -0
  223. package/codeyam-cli/src/utils/editorDeleteScenario.js +67 -0
  224. package/codeyam-cli/src/utils/editorDeleteScenario.js.map +1 -0
  225. package/codeyam-cli/src/utils/editorDevServer.js +197 -0
  226. package/codeyam-cli/src/utils/editorDevServer.js.map +1 -0
  227. package/codeyam-cli/src/utils/editorEntityChangeStatus.js +50 -0
  228. package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -0
  229. package/codeyam-cli/src/utils/editorEntityHelpers.js +144 -0
  230. package/codeyam-cli/src/utils/editorEntityHelpers.js.map +1 -0
  231. package/codeyam-cli/src/utils/editorGuard.js +36 -0
  232. package/codeyam-cli/src/utils/editorGuard.js.map +1 -0
  233. package/codeyam-cli/src/utils/editorImageVerifier.js +155 -0
  234. package/codeyam-cli/src/utils/editorImageVerifier.js.map +1 -0
  235. package/codeyam-cli/src/utils/editorJournal.js +225 -0
  236. package/codeyam-cli/src/utils/editorJournal.js.map +1 -0
  237. package/codeyam-cli/src/utils/editorLoaderHelpers.js +152 -0
  238. package/codeyam-cli/src/utils/editorLoaderHelpers.js.map +1 -0
  239. package/codeyam-cli/src/utils/editorMigration.js +224 -0
  240. package/codeyam-cli/src/utils/editorMigration.js.map +1 -0
  241. package/codeyam-cli/src/utils/editorMockState.js +248 -0
  242. package/codeyam-cli/src/utils/editorMockState.js.map +1 -0
  243. package/codeyam-cli/src/utils/editorPreloadHelpers.js +135 -0
  244. package/codeyam-cli/src/utils/editorPreloadHelpers.js.map +1 -0
  245. package/codeyam-cli/src/utils/editorPreview.js +139 -0
  246. package/codeyam-cli/src/utils/editorPreview.js.map +1 -0
  247. package/codeyam-cli/src/utils/editorRecapture.js +109 -0
  248. package/codeyam-cli/src/utils/editorRecapture.js.map +1 -0
  249. package/codeyam-cli/src/utils/editorScenarioSwitch.js +134 -0
  250. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -0
  251. package/codeyam-cli/src/utils/editorScenarios.js +676 -0
  252. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -0
  253. package/codeyam-cli/src/utils/editorSeedAdapter.js +462 -0
  254. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -0
  255. package/codeyam-cli/src/utils/editorShouldRevalidate.js +21 -0
  256. package/codeyam-cli/src/utils/editorShouldRevalidate.js.map +1 -0
  257. package/codeyam-cli/src/utils/entityChangeStatus.js +394 -0
  258. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -0
  259. package/codeyam-cli/src/utils/entityChangeStatus.server.js +212 -0
  260. package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -0
  261. package/codeyam-cli/src/utils/fileWatcher.js +38 -0
  262. package/codeyam-cli/src/utils/fileWatcher.js.map +1 -1
  263. package/codeyam-cli/src/utils/git.js +51 -0
  264. package/codeyam-cli/src/utils/git.js.map +1 -1
  265. package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
  266. package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
  267. package/codeyam-cli/src/utils/install-skills.js +42 -17
  268. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  269. package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
  270. package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
  271. package/codeyam-cli/src/utils/parseRegisterArg.js +31 -0
  272. package/codeyam-cli/src/utils/parseRegisterArg.js.map +1 -0
  273. package/codeyam-cli/src/utils/progress.js +2 -2
  274. package/codeyam-cli/src/utils/progress.js.map +1 -1
  275. package/codeyam-cli/src/utils/project.js +15 -5
  276. package/codeyam-cli/src/utils/project.js.map +1 -1
  277. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
  278. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
  279. package/codeyam-cli/src/utils/queue/job.js +35 -6
  280. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  281. package/codeyam-cli/src/utils/registerScenarioResult.js +52 -0
  282. package/codeyam-cli/src/utils/registerScenarioResult.js.map +1 -0
  283. package/codeyam-cli/src/utils/routePatternMatching.js +129 -0
  284. package/codeyam-cli/src/utils/routePatternMatching.js.map +1 -0
  285. package/codeyam-cli/src/utils/scenarioCoverage.js +77 -0
  286. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -0
  287. package/codeyam-cli/src/utils/scenarioMarkers.js +134 -0
  288. package/codeyam-cli/src/utils/scenarioMarkers.js.map +1 -0
  289. package/codeyam-cli/src/utils/scenariosManifest.js +307 -0
  290. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -0
  291. package/codeyam-cli/src/utils/screenshotHash.js +26 -0
  292. package/codeyam-cli/src/utils/screenshotHash.js.map +1 -0
  293. package/codeyam-cli/src/utils/serverState.js +30 -0
  294. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  295. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +47 -16
  296. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  297. package/codeyam-cli/src/utils/simulationGateMiddleware.js +17 -1
  298. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
  299. package/codeyam-cli/src/utils/slugUtils.js +25 -0
  300. package/codeyam-cli/src/utils/slugUtils.js.map +1 -0
  301. package/codeyam-cli/src/utils/syncMocksMiddleware.js +2 -2
  302. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  303. package/codeyam-cli/src/utils/telemetry.js +106 -0
  304. package/codeyam-cli/src/utils/telemetry.js.map +1 -0
  305. package/codeyam-cli/src/utils/telemetryMiddleware.js +22 -0
  306. package/codeyam-cli/src/utils/telemetryMiddleware.js.map +1 -0
  307. package/codeyam-cli/src/utils/testRunner.js +200 -2
  308. package/codeyam-cli/src/utils/testRunner.js.map +1 -1
  309. package/codeyam-cli/src/utils/webappDetection.js +21 -0
  310. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  311. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +98 -0
  312. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
  313. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js +35 -0
  314. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js.map +1 -0
  315. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +107 -0
  316. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -0
  317. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +647 -0
  318. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -0
  319. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +283 -0
  320. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -0
  321. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js +135 -0
  322. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js.map +1 -0
  323. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +86 -0
  324. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -0
  325. package/codeyam-cli/src/webserver/app/lib/database.js +41 -27
  326. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  327. package/codeyam-cli/src/webserver/app/lib/git.js +397 -0
  328. package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -0
  329. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
  330. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
  331. package/codeyam-cli/src/webserver/app/types/editor.js +8 -0
  332. package/codeyam-cli/src/webserver/app/types/editor.js.map +1 -0
  333. package/codeyam-cli/src/webserver/backgroundServer.js +60 -61
  334. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  335. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CLe80MMu.js +1 -0
  336. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-C76mRRiF.js → EntityItem-Crt_KN_U.js} +5 -5
  337. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-CQgyEGV-.js +1 -0
  338. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CobE682z.js → EntityTypeIcon-CD7lGABo.js} +9 -9
  339. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-CgTNOhnu.js +1 -0
  340. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-DtYTSPL2.js +25 -0
  341. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-D3s1MFkb.js +3 -0
  342. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-BU_OAEMP.js → LoadingDots-By5zI316.js} +1 -1
  343. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-ceAyBX-H.js → LogViewer-CM5zg40N.js} +3 -3
  344. package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-CQENLSrF.js +36 -0
  345. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-djPLI-WV.js → ReportIssueModal-C2PLkej3.js} +4 -4
  346. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DanvyBPb.js +1 -0
  347. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-B76aig_2.js → ScenarioViewer-CefgqbCr.js} +3 -3
  348. package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bc8BG-Lw.js +34 -0
  349. package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-CK7-NaPZ.js +1 -0
  350. package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-BA_Ry-rs.js +1 -0
  351. package/codeyam-cli/src/webserver/build/client/assets/{_index-C96V0n15.js → _index-C1YkzTAV.js} +4 -4
  352. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BpKzcsJz.js → activity.(_tab)-yH46LLUz.js} +8 -8
  353. package/codeyam-cli/src/webserver/build/client/assets/addon-canvas-DpzMmAy5.js +1 -0
  354. package/codeyam-cli/src/webserver/build/client/assets/addon-fit-YJmn1quW.js +12 -0
  355. package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-Duc5hnl7.js → addon-web-links-CHx25PAe.js} +1 -1
  356. package/codeyam-cli/src/webserver/build/client/assets/addon-webgl-DI8QOUvO.js +58 -0
  357. package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-D9hemwl6.js → agent-transcripts-Bg3e7q4S.js} +7 -7
  358. package/codeyam-cli/src/webserver/build/client/assets/api.editor-audit-l0sNRNKZ.js +1 -0
  359. package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-diff-l0sNRNKZ.js +1 -0
  360. package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-l0sNRNKZ.js +1 -0
  361. package/codeyam-cli/src/webserver/build/client/assets/api.editor-load-commit-l0sNRNKZ.js +1 -0
  362. package/codeyam-cli/src/webserver/build/client/assets/api.editor-project-info-l0sNRNKZ.js +1 -0
  363. package/codeyam-cli/src/webserver/build/client/assets/api.editor-recapture-stale-l0sNRNKZ.js +1 -0
  364. package/codeyam-cli/src/webserver/build/client/assets/api.editor-rename-scenario-l0sNRNKZ.js +1 -0
  365. package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-scenario-data-l0sNRNKZ.js +1 -0
  366. package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-seed-state-l0sNRNKZ.js +1 -0
  367. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-coverage-l0sNRNKZ.js +1 -0
  368. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-prompt-l0sNRNKZ.js +1 -0
  369. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenarios-l0sNRNKZ.js +1 -0
  370. package/codeyam-cli/src/webserver/build/client/assets/api.editor-schema-l0sNRNKZ.js +1 -0
  371. package/codeyam-cli/src/webserver/build/client/assets/api.editor-session-l0sNRNKZ.js +1 -0
  372. package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
  373. package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
  374. package/codeyam-cli/src/webserver/build/client/assets/{book-open-D_nMCFmP.js → book-open-CL-lMgHh.js} +2 -2
  375. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-BH2h1Ea2.js → chevron-down-GmAjGS9-.js} +2 -2
  376. package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-BAdwhyCx.js +43 -0
  377. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-DyIKORY6.js → circle-check-DFcQkN5j.js} +2 -2
  378. package/codeyam-cli/src/webserver/build/client/assets/{copy-NDbZjXao.js → copy-C6iF61Xs.js} +3 -3
  379. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-4ImjHTVC.js +41 -0
  380. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
  381. package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CCKUIm0S.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
  382. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-CRepiabR.js +1 -0
  383. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-Gbk_i5Js.js +1 -0
  384. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-oBrbke_R.js +96 -0
  385. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-CluPkvXJ.js +41 -0
  386. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CrjR3zZW.js → entity._sha._-DYJRGiDI.js} +14 -13
  387. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-wdiwx5-Z.js +6 -0
  388. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-BrkN-40Y.js +6 -0
  389. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DxfhekTZ.js +6 -0
  390. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMvVHNXU.js → entity._sha_.edit._scenarioId-CRXJWmpB.js} +2 -2
  391. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-DTvKq3TY.js → entry.client-SuW9syRS.js} +6 -6
  392. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-Daa96Fr1.js +1 -0
  393. package/codeyam-cli/src/webserver/build/client/assets/files-D-xGrg29.js +1 -0
  394. package/codeyam-cli/src/webserver/build/client/assets/git-Bq_fbXP5.js +1 -0
  395. package/codeyam-cli/src/webserver/build/client/assets/globals-oyPmV37k.css +1 -0
  396. package/codeyam-cli/src/webserver/build/client/assets/{index-BcvgDzbZ.js → index-Bp1l4hSv.js} +1 -1
  397. package/codeyam-cli/src/webserver/build/client/assets/{index-10oVnAAH.js → index-CWV9XZiG.js} +1 -1
  398. package/codeyam-cli/src/webserver/build/client/assets/index-DE3jI_dv.js +15 -0
  399. package/codeyam-cli/src/webserver/build/client/assets/jsx-runtime-D_zvdyIk.js +9 -0
  400. package/codeyam-cli/src/webserver/build/client/assets/labs-B_IX45ih.js +1 -0
  401. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BAXYRVEO.js → loader-circle-De-7qQ2u.js} +2 -2
  402. package/codeyam-cli/src/webserver/build/client/assets/manifest-694b698a.js +1 -0
  403. package/codeyam-cli/src/webserver/build/client/assets/memory-Cx2xEx7s.js +101 -0
  404. package/codeyam-cli/src/webserver/build/client/assets/{pause-DTAcYxBt.js → pause-CFxEKL1u.js} +3 -3
  405. package/codeyam-cli/src/webserver/build/client/assets/root-DXjFYOxD.js +80 -0
  406. package/codeyam-cli/src/webserver/build/client/assets/{search-fKo7v0Zo.js → search-BdBb5aqc.js} +2 -2
  407. package/codeyam-cli/src/webserver/build/client/assets/settings-DdE-Untf.js +1 -0
  408. package/codeyam-cli/src/webserver/build/client/assets/simulations-DSCdE99u.js +1 -0
  409. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BG4heKCG.js → terminal-CrplD4b1.js} +3 -3
  410. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-DtSmdtM4.js → triangle-alert-DqJ0j69l.js} +2 -2
  411. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-DhXHbEjP.js +1 -0
  412. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-D9QZKaLJ.js +2 -0
  413. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-Cy5Qg_UR.js +1 -0
  414. package/codeyam-cli/src/webserver/build/client/assets/useToast-5HR2j9ZE.js +1 -0
  415. package/codeyam-cli/src/webserver/build/client/assets/xterm-BqvuqXEL.js +27 -0
  416. package/codeyam-cli/src/webserver/build/client/sound-test.html +98 -0
  417. package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-zEYtiv0T.js +16 -0
  418. package/codeyam-cli/src/webserver/build/server/assets/index-CcHPEbhi.js +1 -0
  419. package/codeyam-cli/src/webserver/build/server/assets/init-D68IyWbU.js +10 -0
  420. package/codeyam-cli/src/webserver/build/server/assets/progress-CHTtrxFG.js +1 -0
  421. package/codeyam-cli/src/webserver/build/server/assets/server-build-Cxzo0Zp2.js +688 -0
  422. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  423. package/codeyam-cli/src/webserver/build-info.json +5 -5
  424. package/codeyam-cli/src/webserver/editorProxy.js +807 -51
  425. package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
  426. package/codeyam-cli/src/webserver/idleDetector.js +121 -0
  427. package/codeyam-cli/src/webserver/idleDetector.js.map +1 -0
  428. package/codeyam-cli/src/webserver/mockStateEvents.js +28 -0
  429. package/codeyam-cli/src/webserver/mockStateEvents.js.map +1 -0
  430. package/codeyam-cli/src/webserver/public/sound-test.html +98 -0
  431. package/codeyam-cli/src/webserver/scripts/codeyam-preload.mjs +414 -0
  432. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +170 -8
  433. package/codeyam-cli/src/webserver/server.js +214 -12
  434. package/codeyam-cli/src/webserver/server.js.map +1 -1
  435. package/codeyam-cli/src/webserver/terminalServer.js +367 -23
  436. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  437. package/codeyam-cli/templates/__tests__/editor-step-hook.prompt-capture.test.ts +118 -0
  438. package/codeyam-cli/templates/chrome-extension-react/EXTENSION_SETUP.md +75 -0
  439. package/codeyam-cli/templates/chrome-extension-react/README.md +46 -0
  440. package/codeyam-cli/templates/chrome-extension-react/gitignore +15 -0
  441. package/codeyam-cli/templates/chrome-extension-react/index.html +12 -0
  442. package/codeyam-cli/templates/chrome-extension-react/package.json +27 -0
  443. package/codeyam-cli/templates/chrome-extension-react/popup.html +12 -0
  444. package/codeyam-cli/templates/chrome-extension-react/public/manifest.json +15 -0
  445. package/codeyam-cli/templates/chrome-extension-react/src/background/service-worker.ts +7 -0
  446. package/codeyam-cli/templates/chrome-extension-react/src/globals.css +6 -0
  447. package/codeyam-cli/templates/chrome-extension-react/src/lib/storage.ts +37 -0
  448. package/codeyam-cli/templates/chrome-extension-react/src/popup/App.tsx +12 -0
  449. package/codeyam-cli/templates/chrome-extension-react/src/popup/main.tsx +10 -0
  450. package/codeyam-cli/templates/chrome-extension-react/tsconfig.json +24 -0
  451. package/codeyam-cli/templates/chrome-extension-react/vite.config.ts +41 -0
  452. package/codeyam-cli/templates/codeyam-editor-claude.md +86 -5
  453. package/codeyam-cli/templates/codeyam-editor-reference.md +216 -0
  454. package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
  455. package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
  456. package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
  457. package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
  458. package/codeyam-cli/templates/editor-step-hook.py +262 -37
  459. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +89 -0
  460. package/codeyam-cli/templates/expo-react-native/README.md +41 -0
  461. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +33 -0
  462. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +12 -0
  463. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +12 -0
  464. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +12 -0
  465. package/codeyam-cli/templates/expo-react-native/app.json +18 -0
  466. package/codeyam-cli/templates/expo-react-native/babel.config.js +9 -0
  467. package/codeyam-cli/templates/expo-react-native/gitignore +12 -0
  468. package/codeyam-cli/templates/expo-react-native/global.css +3 -0
  469. package/codeyam-cli/templates/expo-react-native/lib/storage.ts +32 -0
  470. package/codeyam-cli/templates/expo-react-native/metro.config.js +6 -0
  471. package/codeyam-cli/templates/expo-react-native/nativewind-env.d.ts +1 -0
  472. package/codeyam-cli/templates/expo-react-native/package.json +38 -0
  473. package/codeyam-cli/templates/expo-react-native/tailwind.config.js +10 -0
  474. package/codeyam-cli/templates/expo-react-native/tsconfig.json +10 -0
  475. package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_PATTERNS.md +308 -0
  476. package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_UPGRADE.md +304 -0
  477. package/codeyam-cli/templates/nextjs-prisma-sqlite/DATABASE.md +126 -0
  478. package/codeyam-cli/templates/nextjs-prisma-sqlite/FEATURE_PATTERNS.md +37 -0
  479. package/codeyam-cli/templates/nextjs-prisma-sqlite/README.md +53 -0
  480. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/codeyam-isolate/layout.tsx +12 -0
  481. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/lib/prisma.ts +9 -4
  482. package/codeyam-cli/templates/nextjs-prisma-sqlite/env +4 -0
  483. package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +64 -0
  484. package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +6 -2
  485. package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma/seed.ts +4 -1
  486. package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +140 -0
  487. package/codeyam-cli/templates/nextjs-prisma-sqlite/vitest.config.ts +13 -0
  488. package/codeyam-cli/templates/nextjs-prisma-supabase/README.md +52 -0
  489. package/codeyam-cli/templates/{nextjs-prisma-sqlite/PRISMA_SETUP.md → nextjs-prisma-supabase/SUPABASE_SETUP.md} +37 -17
  490. package/codeyam-cli/templates/nextjs-prisma-supabase/app/api/todos/route.ts +17 -0
  491. package/codeyam-cli/templates/nextjs-prisma-supabase/app/globals.css +26 -0
  492. package/codeyam-cli/templates/nextjs-prisma-supabase/app/layout.tsx +34 -0
  493. package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/prisma.ts +20 -0
  494. package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/supabase.ts +12 -0
  495. package/codeyam-cli/templates/nextjs-prisma-supabase/app/page.tsx +10 -0
  496. package/codeyam-cli/templates/nextjs-prisma-supabase/env +9 -0
  497. package/codeyam-cli/templates/nextjs-prisma-supabase/eslint.config.mjs +11 -0
  498. package/codeyam-cli/templates/nextjs-prisma-supabase/gitignore +40 -0
  499. package/codeyam-cli/templates/nextjs-prisma-supabase/next.config.ts +11 -0
  500. package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +37 -0
  501. package/codeyam-cli/templates/nextjs-prisma-supabase/postcss.config.mjs +7 -0
  502. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/schema.prisma +27 -0
  503. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/seed.ts +39 -0
  504. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma.config.ts +12 -0
  505. package/codeyam-cli/templates/nextjs-prisma-supabase/tsconfig.json +34 -0
  506. package/codeyam-cli/templates/seed-adapters/supabase.ts +291 -0
  507. package/codeyam-cli/templates/{codeyam-dev-mode.md → skills/codeyam-dev-mode/SKILL.md} +3 -3
  508. package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +229 -0
  509. package/codeyam-cli/templates/{codeyam-memory.md → skills/codeyam-memory/SKILL.md} +215 -0
  510. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/deprecated-prompt.md +100 -0
  511. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.mjs +139 -0
  512. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.mjs +52 -0
  513. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/misleading-api-prompt.md +117 -0
  514. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/read-json-field.mjs +61 -0
  515. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/ripgrep-fallback.mjs +155 -0
  516. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/analyze-prompt.md +46 -0
  517. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.mjs +13 -0
  518. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter-session.mjs +95 -0
  519. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.mjs +160 -0
  520. package/package.json +16 -10
  521. package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
  522. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  523. package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
  524. package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
  525. package/packages/ai/src/lib/astScopes/paths.js +12 -3
  526. package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
  527. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +27 -10
  528. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  529. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
  530. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
  531. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
  532. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  533. package/packages/ai/src/lib/generateExecutionFlows.js +0 -11
  534. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  535. package/packages/analyze/index.js +1 -1
  536. package/packages/analyze/index.js.map +1 -1
  537. package/packages/analyze/src/lib/ProjectAnalyzer.js +10 -4
  538. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  539. package/packages/analyze/src/lib/asts/index.js +4 -2
  540. package/packages/analyze/src/lib/asts/index.js.map +1 -1
  541. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
  542. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  543. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
  544. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  545. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +3 -2
  546. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
  547. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +9 -7
  548. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  549. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
  550. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
  551. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
  552. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  553. package/packages/analyze/src/lib/files/analyzeChange.js +1 -0
  554. package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
  555. package/packages/analyze/src/lib/files/analyzeInitial.js +1 -0
  556. package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
  557. package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
  558. package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
  559. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +120 -28
  560. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  561. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +0 -40
  562. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  563. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1368 -1193
  564. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  565. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +104 -0
  566. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  567. package/packages/database/src/lib/loadAnalysis.js +7 -1
  568. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  569. package/packages/database/src/lib/loadEntities.js +0 -6
  570. package/packages/database/src/lib/loadEntities.js.map +1 -1
  571. package/packages/database/src/lib/loadEntity.js +5 -5
  572. package/packages/database/src/lib/loadEntity.js.map +1 -1
  573. package/packages/database/src/lib/updateCommitMetadata.js +0 -25
  574. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  575. package/packages/types/src/enums/ProjectFramework.js +2 -0
  576. package/packages/types/src/enums/ProjectFramework.js.map +1 -1
  577. package/packages/utils/src/lib/fs/rsyncCopy.js +22 -1
  578. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  579. package/scripts/npm-post-install.cjs +34 -0
  580. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-DmJveP3T.js +0 -1
  581. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-g3saevPb.js +0 -1
  582. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-Bu6c6aDe.js +0 -1
  583. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-DYFW3lDD.js +0 -25
  584. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DLeucoVX.js +0 -3
  585. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BED4B6sP.js +0 -1
  586. package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bb5uFQ5V.js +0 -34
  587. package/codeyam-cli/src/webserver/build/client/assets/Terminal-BaIiqg_w.js +0 -41
  588. package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-C8OKAR5x.js +0 -1
  589. package/codeyam-cli/src/webserver/build/client/assets/addon-fit-CUXOrorO.js +0 -1
  590. package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-C4pqxYJB.js +0 -51
  591. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CMT1jU2q.js +0 -21
  592. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +0 -1
  593. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BiM6z3Do.js +0 -1
  594. package/codeyam-cli/src/webserver/build/client/assets/editor-BaC8lHDG.js +0 -7
  595. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-DloHYjtt.js +0 -6
  596. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-C28BiQzt.js +0 -6
  597. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-p9hhkjJM.js +0 -6
  598. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-cPo8LiG3.js +0 -1
  599. package/codeyam-cli/src/webserver/build/client/assets/files-DO4CZ16O.js +0 -1
  600. package/codeyam-cli/src/webserver/build/client/assets/git-CFCTYk9I.js +0 -15
  601. package/codeyam-cli/src/webserver/build/client/assets/globals-BH6uYxPM.css +0 -1
  602. package/codeyam-cli/src/webserver/build/client/assets/labs-Zk7ryIM1.js +0 -1
  603. package/codeyam-cli/src/webserver/build/client/assets/manifest-fb3128c3.js +0 -1
  604. package/codeyam-cli/src/webserver/build/client/assets/memory-FweZHj5U.js +0 -93
  605. package/codeyam-cli/src/webserver/build/client/assets/root-Dzn8nIkU.js +0 -67
  606. package/codeyam-cli/src/webserver/build/client/assets/settings-DfuTtcJP.js +0 -1
  607. package/codeyam-cli/src/webserver/build/client/assets/simulations-B3aOzpCZ.js +0 -1
  608. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-ByhSyh0W.js +0 -1
  609. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C14nCb1q.js +0 -2
  610. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-O-jkvSPx.js +0 -1
  611. package/codeyam-cli/src/webserver/build/client/assets/useToast-9FIWuYfK.js +0 -1
  612. package/codeyam-cli/src/webserver/build/client/assets/xterm-DMSzMhqy.js +0 -9
  613. package/codeyam-cli/src/webserver/build/server/assets/index-DeSuKbSF.js +0 -1
  614. package/codeyam-cli/src/webserver/build/server/assets/server-build-BbQ8YBP-.js +0 -362
  615. package/codeyam-cli/templates/codeyam-editor.md +0 -67
  616. package/scripts/finalize-analyzer.cjs +0 -13
  617. /package/codeyam-cli/templates/{codeyam-diagnose.md → commands/codeyam-diagnose.md} +0 -0
  618. /package/codeyam-cli/templates/{codeyam-debug.md → skills/codeyam-debug/SKILL.md} +0 -0
  619. /package/codeyam-cli/templates/{codeyam-new-rule.md → skills/codeyam-new-rule/SKILL.md} +0 -0
  620. /package/codeyam-cli/templates/{codeyam-setup.md → skills/codeyam-setup/SKILL.md} +0 -0
  621. /package/codeyam-cli/templates/{codeyam-sim.md → skills/codeyam-sim/SKILL.md} +0 -0
  622. /package/codeyam-cli/templates/{codeyam-test.md → skills/codeyam-test/SKILL.md} +0 -0
  623. /package/codeyam-cli/templates/{codeyam-verify.md → skills/codeyam-verify/SKILL.md} +0 -0
@@ -3,16 +3,204 @@ import net from 'net';
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import { getProjectRoot } from "../state.js";
6
+ import { createMockStateManager, } from "../utils/editorMockState.js";
7
+ import { computeEditorPorts } from "../utils/editorDevServer.js";
8
+ import { mockStateEventEmitter } from "./mockStateEvents.js";
9
+ /**
10
+ * Normalize a target URL by stripping trailing slashes for consistency.
11
+ *
12
+ * Previously this also replaced `localhost` with `127.0.0.1`, but that broke
13
+ * forwarding to dev servers that bind to IPv6 only (e.g. Vite 6 on macOS
14
+ * binds to `[::1]`). The hostname is now left as-is — `resolveLoopbackAddress`
15
+ * probes the actual target at startup to pick the right address.
16
+ */
17
+ export function normalizeTargetUrl(url) {
18
+ try {
19
+ const parsed = new URL(url);
20
+ return parsed.toString().replace(/\/$/, '');
21
+ }
22
+ catch {
23
+ return url;
24
+ }
25
+ }
26
+ /**
27
+ * Probe a localhost port to determine the correct loopback address.
28
+ * Dev servers may bind to IPv4 (127.0.0.1), IPv6 (::1), or both.
29
+ * Returns the first address that accepts a TCP connection.
30
+ */
31
+ export async function resolveLoopbackAddress(port) {
32
+ const candidates = ['127.0.0.1', '::1'];
33
+ for (const host of candidates) {
34
+ try {
35
+ const connected = await new Promise((resolve) => {
36
+ const socket = new net.Socket();
37
+ socket.setTimeout(1000);
38
+ socket.once('connect', () => {
39
+ socket.destroy();
40
+ resolve(true);
41
+ });
42
+ socket.once('error', () => {
43
+ socket.destroy();
44
+ resolve(false);
45
+ });
46
+ socket.once('timeout', () => {
47
+ socket.destroy();
48
+ resolve(false);
49
+ });
50
+ socket.connect(port, host);
51
+ });
52
+ if (connected) {
53
+ return host;
54
+ }
55
+ }
56
+ catch {
57
+ // Try next candidate
58
+ }
59
+ }
60
+ return null;
61
+ }
6
62
  // Global key so the proxy survives HMR
7
63
  const GLOBAL_KEY = '__codeyam_editor_proxy__';
64
+ // ─── Live Preview Health ─────────────────────────────────────────────
65
+ const PREVIEW_HEALTH_KEY = '__codeyam_preview_health__';
66
+ function getPreviewHealth() {
67
+ return globalThis[PREVIEW_HEALTH_KEY] ?? null;
68
+ }
69
+ function setPreviewHealth(report) {
70
+ globalThis[PREVIEW_HEALTH_KEY] = report;
71
+ }
72
+ /**
73
+ * Get the current live preview health report (read by API endpoint).
74
+ */
75
+ export function getPreviewHealthReport() {
76
+ return getPreviewHealth();
77
+ }
78
+ /**
79
+ * Reset preview health state (called when a new HTML page is served).
80
+ */
81
+ export function resetPreviewHealth() {
82
+ setPreviewHealth(null);
83
+ }
84
+ /**
85
+ * Error-catching script injected into HTML responses.
86
+ * Uses vanilla JS for maximum compatibility.
87
+ */
88
+ export const PREVIEW_HEALTH_SCRIPT = `<script data-codeyam-health>
89
+ (function() {
90
+ var errors = [];
91
+ var reported = false;
92
+ function report(type, msg, stack) {
93
+ errors.push({ type: type, message: msg, stack: stack, timestamp: Date.now() });
94
+ if (!reported) {
95
+ reported = true;
96
+ setTimeout(function() { flush(); }, 500);
97
+ }
98
+ }
99
+ function flush() {
100
+ fetch('/__codeyam__/preview-health', {
101
+ method: 'POST',
102
+ headers: { 'Content-Type': 'application/json' },
103
+ body: JSON.stringify({ errors: errors, url: location.href })
104
+ }).catch(function(){});
105
+ reported = false;
106
+ errors = [];
107
+ }
108
+ window.addEventListener('error', function(e) {
109
+ report('error', e.message, e.error && e.error.stack);
110
+ });
111
+ window.addEventListener('unhandledrejection', function(e) {
112
+ report('unhandledrejection', String(e.reason), e.reason && e.reason.stack);
113
+ });
114
+ var origError = console.error;
115
+ console.error = function() {
116
+ report('console.error', Array.prototype.join.call(arguments, ' '));
117
+ origError.apply(console, arguments);
118
+ };
119
+ window.addEventListener('load', function() {
120
+ setTimeout(function() {
121
+ var hasContent = document.body && document.body.innerText.trim().length > 0;
122
+ fetch('/__codeyam__/preview-health', {
123
+ method: 'POST',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify({
126
+ loaded: true,
127
+ hasContent: hasContent,
128
+ url: location.href,
129
+ errorCount: errors.length
130
+ })
131
+ }).catch(function(){});
132
+ }, 1000);
133
+ });
134
+
135
+ // Network-idle detection: notify the parent editor when all initial
136
+ // fetch requests have completed, so it can show the preview after
137
+ // client-side data (API calls) has arrived — not just when the DOM loads.
138
+ var inflight = 0;
139
+ var settled = false;
140
+ var settleTimer = null;
141
+ var origFetch = window.fetch;
142
+ window.fetch = function() {
143
+ if (!settled) inflight++;
144
+ return origFetch.apply(this, arguments).then(function(resp) {
145
+ if (!settled) { inflight--; checkSettle(); }
146
+ return resp;
147
+ }, function(err) {
148
+ if (!settled) { inflight--; checkSettle(); }
149
+ throw err;
150
+ });
151
+ };
152
+ function checkSettle() {
153
+ if (inflight <= 0 && !settled) {
154
+ clearTimeout(settleTimer);
155
+ // Small delay to allow React to re-render with the fetched data
156
+ settleTimer = setTimeout(function() {
157
+ if (inflight <= 0) {
158
+ settled = true;
159
+ try {
160
+ window.parent.postMessage({ type: 'codeyam-preview-ready' }, '*');
161
+ } catch(e) {}
162
+ }
163
+ }, 100);
164
+ }
165
+ }
166
+ // Fallback: if no fetches happen (static page), settle after load
167
+ window.addEventListener('load', function() {
168
+ setTimeout(function() { checkSettle(); }, 200);
169
+ });
170
+ })();
171
+ </script>`;
8
172
  const CACHE_TTL_MS = 500;
9
173
  let scenarioCache = { data: null, timestamp: 0 };
174
+ // Session config extracted from the active scenario — drives cookie injection
175
+ let sessionConfig = undefined;
176
+ /** Session cookies from the seed adapter (e.g. Supabase auth tokens). */
177
+ let seedSessionCookies = undefined;
178
+ // localStorage config extracted from the active scenario — drives HTML injection
179
+ let localStorageConfig = null;
180
+ // Active scenario ID — used to gate localStorage seeding (only re-seed on switch)
181
+ let activeScenarioId = null;
182
+ // Prototype ID — used to gate a one-time localStorage.clear() when a new project is scaffolded
183
+ let currentPrototypeId = null;
184
+ // Current scenario type — 'application'/'user' for seed-based, 'component' for mock-based
185
+ let currentScenarioType = null;
186
+ // Max body size to buffer for mock matching (10MB)
187
+ const MAX_BODY_SIZE = 10 * 1024 * 1024;
10
188
  function getProxyState() {
11
189
  return globalThis[GLOBAL_KEY] ?? null;
12
190
  }
13
191
  function setProxyState(state) {
14
192
  globalThis[GLOBAL_KEY] = state;
15
193
  }
194
+ /**
195
+ * Get or create the mock state manager (survives HMR via globalThis).
196
+ */
197
+ function getMockStateManager() {
198
+ const key = '__codeyam_mock_state__';
199
+ if (!globalThis[key]) {
200
+ globalThis[key] = createMockStateManager();
201
+ }
202
+ return globalThis[key];
203
+ }
16
204
  /**
17
205
  * Get the proxy URL if the proxy is running.
18
206
  */
@@ -24,6 +212,13 @@ export function getProxyUrl() {
24
212
  }
25
213
  /**
26
214
  * Read the active scenario's mock data from disk, with brief caching.
215
+ * Feeds the data into the MockStateManager.
216
+ *
217
+ * For application/user scenarios (type-aware): only loads `externalApis`
218
+ * into the mock state manager. All DB-backed routes flow through to the
219
+ * real app (database is seeded with real data).
220
+ *
221
+ * For component scenarios (or legacy): loads all routes as before.
27
222
  */
28
223
  function readScenarioData() {
29
224
  const now = Date.now();
@@ -41,6 +236,8 @@ function readScenarioData() {
41
236
  const active = JSON.parse(fs.readFileSync(activeScenarioPath, 'utf-8'));
42
237
  const scenarioId = active.scenarioId;
43
238
  if (!scenarioId) {
239
+ // No active scenario — but may have a prototypeId for localStorage clearing
240
+ currentPrototypeId = active.prototypeId || null;
44
241
  scenarioCache = { data: null, timestamp: now };
45
242
  return null;
46
243
  }
@@ -50,9 +247,37 @@ function readScenarioData() {
50
247
  scenarioCache = { data: null, timestamp: now };
51
248
  return null;
52
249
  }
53
- const data = JSON.parse(fs.readFileSync(dataFilePath, 'utf-8'));
54
- scenarioCache = { data, timestamp: now };
55
- return data;
250
+ const rawData = JSON.parse(fs.readFileSync(dataFilePath, 'utf-8'));
251
+ // Extract session config for cookie injection
252
+ sessionConfig = rawData.session || null;
253
+ // Extract seed adapter session cookies (e.g. Supabase auth)
254
+ seedSessionCookies = rawData.sessionCookies || undefined;
255
+ // Extract localStorage config for HTML injection
256
+ localStorageConfig = rawData.localStorage || null;
257
+ activeScenarioId = scenarioId;
258
+ // Type-aware: for seed-based scenarios, only serve externalApis via proxy
259
+ const scenarioType = active.type || rawData.type || null;
260
+ currentScenarioType = scenarioType;
261
+ let mockData;
262
+ if ((scenarioType === 'application' || scenarioType === 'user') &&
263
+ rawData.seed) {
264
+ // Seed-based scenario: only load externalApis as routes for the proxy
265
+ if (rawData.externalApis && typeof rawData.externalApis === 'object') {
266
+ mockData = { routes: rawData.externalApis };
267
+ }
268
+ else {
269
+ // No external APIs — proxy passes everything through
270
+ mockData = {};
271
+ }
272
+ }
273
+ else {
274
+ // Component/legacy scenario: load all data
275
+ mockData = rawData;
276
+ }
277
+ scenarioCache = { data: mockData, timestamp: now };
278
+ // Feed into mock state manager (smart reload handles dedup)
279
+ getMockStateManager().loadScenario(mockData);
280
+ return mockData;
56
281
  }
57
282
  catch (err) {
58
283
  console.warn('[editorProxy] Error reading scenario data:', err);
@@ -61,50 +286,163 @@ function readScenarioData() {
61
286
  }
62
287
  }
63
288
  /**
64
- * Find a matching route in the scenario data.
65
- *
66
- * Supports two formats:
67
- * - New route-keyed: { "routes": { "/api/drinks": { "body": [...] } } }
68
- * - Legacy key-based: { "drinks": [...] } → matches /api/drinks
289
+ * Buffer the request body, up to MAX_BODY_SIZE.
290
+ * Returns null if the body exceeds the limit.
69
291
  */
70
- export function findMatchingRoute(pathname, scenarioData) {
71
- // New format: check routes map
72
- const routes = scenarioData.routes;
73
- if (routes && typeof routes === 'object') {
74
- const routeEntry = routes[pathname];
75
- if (routeEntry && typeof routeEntry === 'object') {
76
- const entry = routeEntry;
77
- return {
78
- body: entry.body ?? routeEntry,
79
- status: typeof entry.status === 'number' ? entry.status : 200,
80
- };
81
- }
292
+ function bufferRequestBody(req) {
293
+ return new Promise((resolve) => {
294
+ const chunks = [];
295
+ let totalSize = 0;
296
+ req.on('data', (chunk) => {
297
+ totalSize += chunk.length;
298
+ if (totalSize > MAX_BODY_SIZE) {
299
+ resolve(null); // Too large — skip mock matching
300
+ req.resume(); // Drain remaining
301
+ }
302
+ else {
303
+ chunks.push(chunk);
304
+ }
305
+ });
306
+ req.on('end', () => {
307
+ if (totalSize > MAX_BODY_SIZE)
308
+ return; // Already resolved
309
+ resolve(Buffer.concat(chunks));
310
+ });
311
+ req.on('error', () => {
312
+ resolve(null);
313
+ });
314
+ });
315
+ }
316
+ /**
317
+ * Strip IPv6 bracket notation for use with http.request hostname.
318
+ * URL.hostname returns `[::1]` for IPv6 but http.request needs `::1`.
319
+ */
320
+ function stripIPv6Brackets(hostname) {
321
+ if (hostname.startsWith('[') && hostname.endsWith(']')) {
322
+ return hostname.slice(1, -1);
323
+ }
324
+ return hostname;
325
+ }
326
+ /**
327
+ * Forward a buffered request to the target dev server.
328
+ * Unlike the streaming forwardRequest, this replays a buffered body.
329
+ */
330
+ function forwardBufferedRequest(req, res, targetUrl, bodyBuffer) {
331
+ const target = new URL(targetUrl);
332
+ const hostname = stripIPv6Brackets(target.hostname);
333
+ const headers = { ...req.headers, host: `${target.hostname}:${target.port}` };
334
+ // Remove accept-encoding so the dev server returns uncompressed responses.
335
+ // The proxy injects a health script into HTML — this fails on compressed bodies.
336
+ delete headers['accept-encoding'];
337
+ // Update content-length if we have the body buffer
338
+ if (bodyBuffer) {
339
+ headers['content-length'] = String(bodyBuffer.length);
82
340
  }
83
- // Legacy format: key "drinks" matches "/api/drinks"
84
- // Extract the last segment of the path after /api/
85
- const apiMatch = pathname.match(/^\/api\/(.+)$/);
86
- if (apiMatch) {
87
- const key = apiMatch[1];
88
- if (key in scenarioData && key !== 'routes') {
89
- return { body: scenarioData[key], status: 200 };
341
+ const options = {
342
+ hostname,
343
+ port: target.port,
344
+ path: req.url,
345
+ method: req.method,
346
+ headers,
347
+ };
348
+ const proxyReq = http.request(options, (proxyRes) => {
349
+ const status = proxyRes.statusCode || 200;
350
+ if (status >= 400) {
351
+ console.warn(`[editorProxy] Target returned ${status} for ${req.method} ${req.url}`);
352
+ }
353
+ const headers = { ...proxyRes.headers };
354
+ injectSessionCookie(headers);
355
+ // Check if response is HTML — if so, buffer and inject health script
356
+ const contentType = proxyRes.headers['content-type'] || '';
357
+ if (contentType.includes('text/html')) {
358
+ resetPreviewHealth();
359
+ const chunks = [];
360
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
361
+ proxyRes.on('end', () => {
362
+ const body = Buffer.concat(chunks).toString('utf-8');
363
+ const lsScript = buildLocalStorageScript(localStorageConfig, activeScenarioId || '', currentPrototypeId);
364
+ const injected = injectHealthScript(body, lsScript);
365
+ delete headers['content-length'];
366
+ delete headers['content-encoding'];
367
+ // Prevent browser from caching HTML responses — scenario switches
368
+ // serve different content from the same URL (seed data changes the
369
+ // rendered page but the proxy URL stays the same).
370
+ headers['cache-control'] = 'no-store, must-revalidate';
371
+ res.writeHead(status, headers);
372
+ res.end(injected);
373
+ });
374
+ return;
375
+ }
376
+ res.writeHead(status, headers);
377
+ proxyRes.pipe(res, { end: true });
378
+ });
379
+ proxyReq.on('error', (err) => {
380
+ console.warn(`[editorProxy] Forward error for ${req.method} ${req.url}: ${err.message}`);
381
+ if (!res.headersSent) {
382
+ res.writeHead(502, { 'Content-Type': 'text/plain' });
383
+ res.end('Bad Gateway — dev server unreachable');
90
384
  }
385
+ });
386
+ if (bodyBuffer && bodyBuffer.length > 0) {
387
+ proxyReq.end(bodyBuffer);
388
+ }
389
+ else {
390
+ proxyReq.end();
91
391
  }
92
- return null;
93
392
  }
94
393
  /**
95
394
  * Forward an HTTP request to the target dev server.
395
+ * For HTML responses: buffers body to inject health-check script.
396
+ * For non-HTML responses: pipes directly (no buffering).
96
397
  */
97
398
  function forwardRequest(req, res, targetUrl) {
98
399
  const target = new URL(targetUrl);
400
+ const hostname = stripIPv6Brackets(target.hostname);
401
+ // Build headers, stripping accept-encoding so the dev server returns uncompressed
402
+ // responses. The proxy injects a health script into HTML — this fails on compressed bodies.
403
+ const { 'accept-encoding': _ae, ...forwardHeaders } = req.headers;
99
404
  const options = {
100
- hostname: target.hostname,
405
+ hostname,
101
406
  port: target.port,
102
407
  path: req.url,
103
408
  method: req.method,
104
- headers: { ...req.headers, host: `${target.hostname}:${target.port}` },
409
+ headers: {
410
+ ...forwardHeaders,
411
+ host: `${target.hostname}:${target.port}`,
412
+ },
105
413
  };
106
414
  const proxyReq = http.request(options, (proxyRes) => {
107
- res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
415
+ const status = proxyRes.statusCode || 200;
416
+ if (status >= 400) {
417
+ console.warn(`[editorProxy] Target returned ${status} for ${req.method} ${req.url}`);
418
+ }
419
+ const headers = { ...proxyRes.headers };
420
+ injectSessionCookie(headers);
421
+ // Check if response is HTML — if so, buffer and inject health script
422
+ const contentType = proxyRes.headers['content-type'] || '';
423
+ if (contentType.includes('text/html')) {
424
+ // Reset health state for new page loads
425
+ resetPreviewHealth();
426
+ const chunks = [];
427
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
428
+ proxyRes.on('end', () => {
429
+ const body = Buffer.concat(chunks).toString('utf-8');
430
+ const lsScript = buildLocalStorageScript(localStorageConfig, activeScenarioId || '', currentPrototypeId);
431
+ const injected = injectHealthScript(body, lsScript);
432
+ // Remove content-length since body size changed; use chunked transfer
433
+ delete headers['content-length'];
434
+ // Remove content-encoding since we're serving uncompressed
435
+ delete headers['content-encoding'];
436
+ // Prevent browser from caching HTML responses — scenario switches
437
+ // serve different content from the same URL (seed data changes the
438
+ // rendered page but the proxy URL stays the same).
439
+ headers['cache-control'] = 'no-store, must-revalidate';
440
+ res.writeHead(status, headers);
441
+ res.end(injected);
442
+ });
443
+ return;
444
+ }
445
+ res.writeHead(status, headers);
108
446
  proxyRes.pipe(res, { end: true });
109
447
  });
110
448
  proxyReq.on('error', (err) => {
@@ -116,14 +454,267 @@ function forwardRequest(req, res, targetUrl) {
116
454
  });
117
455
  req.pipe(proxyReq, { end: true });
118
456
  }
457
+ /**
458
+ * Inject or clear the session-token cookie on proxied responses.
459
+ * When a scenario has session.cookieValue, sets the cookie to auto-log the user in.
460
+ * When a scenario has no session field (null), clears any existing session cookie.
461
+ * When sessionConfig is undefined (no scenario loaded yet), does nothing.
462
+ */
463
+ function injectSessionCookie(headers) {
464
+ const cookies = [];
465
+ // Dev auth cookie (built-in session-token)
466
+ if (sessionConfig !== undefined) {
467
+ if (sessionConfig?.cookieValue) {
468
+ cookies.push(`session-token=${sessionConfig.cookieValue}; Path=/; SameSite=Lax`);
469
+ }
470
+ else {
471
+ cookies.push(`session-token=; Path=/; Max-Age=0`);
472
+ }
473
+ }
474
+ // Seed adapter session cookies (e.g. Supabase auth tokens)
475
+ if (seedSessionCookies && seedSessionCookies.length > 0) {
476
+ for (const sc of seedSessionCookies) {
477
+ const cookiePath = sc.path || '/';
478
+ const sameSite = sc.sameSite || 'Lax';
479
+ cookies.push(`${sc.name}=${sc.value}; Path=${cookiePath}; SameSite=${sameSite}`);
480
+ }
481
+ }
482
+ if (cookies.length === 0)
483
+ return;
484
+ const existing = headers['set-cookie'];
485
+ if (existing) {
486
+ headers['set-cookie'] = [
487
+ ...(Array.isArray(existing) ? existing : [existing]),
488
+ ...cookies,
489
+ ];
490
+ }
491
+ else {
492
+ headers['set-cookie'] = cookies;
493
+ }
494
+ }
495
+ /**
496
+ * Get the current session config (for testing).
497
+ */
498
+ export function getSessionConfig() {
499
+ return sessionConfig;
500
+ }
501
+ /**
502
+ * Get the current localStorage config (for testing and script generation).
503
+ */
504
+ export function getLocalStorageConfig() {
505
+ return localStorageConfig;
506
+ }
507
+ /**
508
+ * Get the active scenario ID (for testing and script generation).
509
+ */
510
+ export function getActiveScenarioId() {
511
+ return activeScenarioId;
512
+ }
513
+ /**
514
+ * Get the current prototype ID (for testing).
515
+ */
516
+ export function getCurrentPrototypeId() {
517
+ return currentPrototypeId;
518
+ }
519
+ /**
520
+ * Simple djb2 hash — fast, deterministic, good enough for cache busting.
521
+ * Not cryptographic — just detects when localStorage config content changes.
522
+ */
523
+ function simpleHash(str) {
524
+ let hash = 5381;
525
+ for (let i = 0; i < str.length; i++) {
526
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;
527
+ }
528
+ return (hash >>> 0).toString(36);
529
+ }
530
+ /**
531
+ * Build a script tag that seeds localStorage with scenario data on first load.
532
+ * Gated by scenario ID — only seeds when the scenario changes, preserving
533
+ * interactive modifications across page reloads / HMR.
534
+ *
535
+ * Returns empty string if no localStorage config is provided.
536
+ */
537
+ export function buildLocalStorageScript(localStorageConfig, scenarioId, prototypeId) {
538
+ // null/undefined means no localStorage config at all — clean up keys
539
+ // that were set by a previous scenario so stale filter/sort state
540
+ // doesn't bleed through and hide data in the new scenario.
541
+ if (!localStorageConfig || typeof localStorageConfig !== 'object') {
542
+ // Always clean up previous scenario's keys, gated by scenarioId
543
+ // so it only runs once per switch (not on every HMR reload).
544
+ const guardValue = scenarioId ? `clear:${scenarioId}` : '';
545
+ if (prototypeId) {
546
+ return `<script data-codeyam-ls>
547
+ (function() {
548
+ if (localStorage.getItem('__codeyam_proto__') === ${JSON.stringify(prototypeId)}) return;
549
+ localStorage.clear();
550
+ localStorage.setItem('__codeyam_proto__', ${JSON.stringify(prototypeId)});
551
+ })();
552
+ </script>`;
553
+ }
554
+ if (scenarioId) {
555
+ // No prototypeId but we do have a scenarioId — clean up keys
556
+ // from the previous scenario without doing a full clear.
557
+ return `<script data-codeyam-ls>
558
+ (function() {
559
+ if (localStorage.getItem('__codeyam_ls_sid__') === ${JSON.stringify(guardValue)}) return;
560
+ var prev = JSON.parse(localStorage.getItem('__codeyam_ls_keys__') || '[]');
561
+ for (var i = 0; i < prev.length; i++) localStorage.removeItem(prev[i]);
562
+ localStorage.removeItem('__codeyam_ls_keys__');
563
+ localStorage.setItem('__codeyam_ls_sid__', ${JSON.stringify(guardValue)});
564
+ })();
565
+ </script>`;
566
+ }
567
+ return '';
568
+ }
569
+ // Even an empty object needs a cleanup script — switching from a scenario
570
+ // with localStorage data to one without must clear the previous keys.
571
+ const entries = Object.entries(localStorageConfig);
572
+ const keys = entries.map(([k]) => k);
573
+ // Build setItem calls — stringify non-string values
574
+ const setStatements = entries
575
+ .map(([key, value]) => {
576
+ const serialized = typeof value === 'string' ? value : JSON.stringify(value);
577
+ return `localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(serialized)});`;
578
+ })
579
+ .join('\n');
580
+ // Guard value includes a content hash so re-registering a scenario with
581
+ // updated data (same ID, different content) busts the cache. Without this,
582
+ // the browser skips re-seeding because the scenario ID hasn't changed,
583
+ // causing stale data in the live preview while screenshots show fresh data.
584
+ const contentHash = simpleHash(JSON.stringify(localStorageConfig));
585
+ const guardValue = `${scenarioId}:${contentHash}`;
586
+ return (`<script data-codeyam-ls>
587
+ (function() {
588
+ if (localStorage.getItem('__codeyam_ls_sid__') === ${JSON.stringify(guardValue)}) return;
589
+ var prev = JSON.parse(localStorage.getItem('__codeyam_ls_keys__') || '[]');
590
+ for (var i = 0; i < prev.length; i++) localStorage.removeItem(prev[i]);
591
+ ${setStatements}
592
+ localStorage.setItem('__codeyam_ls_keys__', ${JSON.stringify(JSON.stringify(keys))});
593
+ localStorage.setItem('__codeyam_ls_sid__', ${JSON.stringify(guardValue)});
594
+ })();
595
+ </script>` + buildLocalStorageWatcherScript());
596
+ }
597
+ /**
598
+ * Build a script that watches for localStorage mutations and notifies the parent
599
+ * frame via postMessage. Also responds to `codeyam-get-localstorage` requests so
600
+ * the editor can read the current localStorage state when saving.
601
+ */
602
+ function buildLocalStorageWatcherScript() {
603
+ return `<script data-codeyam-ls-watcher>
604
+ (function() {
605
+ if (window.__codeyam_ls_watcher_installed__) return;
606
+ window.__codeyam_ls_watcher_installed__ = true;
607
+
608
+ var origSet = localStorage.setItem.bind(localStorage);
609
+ var origRemove = localStorage.removeItem.bind(localStorage);
610
+ var origClear = localStorage.clear.bind(localStorage);
611
+ window.__codeyam_orig_setItem__ = origSet;
612
+ window.__codeyam_orig_removeItem__ = origRemove;
613
+ window.__codeyam_orig_clear__ = origClear;
614
+
615
+ function isInternal(key) {
616
+ return typeof key === 'string' && key.indexOf('__codeyam_') === 0;
617
+ }
618
+
619
+ localStorage.setItem = function(key, value) {
620
+ origSet(key, value);
621
+ if (!isInternal(key) && window.parent !== window) {
622
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'set', key: key }, '*');
623
+ }
624
+ };
625
+
626
+ localStorage.removeItem = function(key) {
627
+ origRemove(key);
628
+ if (!isInternal(key) && window.parent !== window) {
629
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'remove', key: key }, '*');
630
+ }
631
+ };
632
+
633
+ localStorage.clear = function() {
634
+ origClear();
635
+ if (window.parent !== window) {
636
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'clear' }, '*');
637
+ }
638
+ };
639
+
640
+ window.addEventListener('message', function(event) {
641
+ if (event.data && event.data.type === 'codeyam-get-localstorage') {
642
+ var data = {};
643
+ for (var i = 0; i < localStorage.length; i++) {
644
+ var k = localStorage.key(i);
645
+ if (k && !isInternal(k)) {
646
+ data[k] = localStorage.getItem(k);
647
+ }
648
+ }
649
+ event.source.postMessage({ type: 'codeyam-localstorage-state', data: data }, '*');
650
+ }
651
+ });
652
+ })();
653
+ </script>`;
654
+ }
655
+ /**
656
+ * Inject the health-check script (and optional localStorage script) into an HTML response body.
657
+ * Inserts before </head> if present, otherwise before </body>, otherwise appends.
658
+ * When a localStorageScript is provided, it's injected BEFORE the health script
659
+ * so localStorage is populated before the app loads.
660
+ */
661
+ export function injectHealthScript(html, localStorageScript) {
662
+ const scripts = (localStorageScript || '') + PREVIEW_HEALTH_SCRIPT;
663
+ if (html.includes('</head>')) {
664
+ return html.replace('</head>', scripts + '</head>');
665
+ }
666
+ if (html.includes('</body>')) {
667
+ return html.replace('</body>', scripts + '</body>');
668
+ }
669
+ return html + scripts;
670
+ }
671
+ /**
672
+ * Handle POST /__codeyam__/preview-health — store health data in globalThis.
673
+ */
674
+ function handlePreviewHealthPost(req, res) {
675
+ const chunks = [];
676
+ req.on('data', (chunk) => chunks.push(chunk));
677
+ req.on('end', () => {
678
+ try {
679
+ const body = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
680
+ const current = getPreviewHealth() || {
681
+ errors: [],
682
+ loaded: false,
683
+ hasContent: false,
684
+ url: '',
685
+ lastUpdated: 0,
686
+ };
687
+ if (body.errors && Array.isArray(body.errors)) {
688
+ current.errors = current.errors.concat(body.errors);
689
+ }
690
+ if (body.loaded !== undefined) {
691
+ current.loaded = body.loaded;
692
+ }
693
+ if (body.hasContent !== undefined) {
694
+ current.hasContent = body.hasContent;
695
+ }
696
+ if (body.url) {
697
+ current.url = body.url;
698
+ }
699
+ current.lastUpdated = Date.now();
700
+ setPreviewHealth(current);
701
+ }
702
+ catch {
703
+ // Ignore malformed JSON
704
+ }
705
+ res.writeHead(204);
706
+ res.end();
707
+ });
708
+ }
119
709
  /**
120
710
  * Handle WebSocket upgrade by piping to the target dev server.
121
711
  */
122
712
  function handleUpgrade(req, socket, head, targetUrl) {
123
713
  const target = new URL(targetUrl);
714
+ const hostname = stripIPv6Brackets(target.hostname);
124
715
  const port = parseInt(target.port, 10) || 80;
125
- console.log(`[editorProxy] WebSocket upgrade: ${req.url} → ${target.hostname}:${port}`);
126
- const proxySocket = net.connect(port, target.hostname, () => {
716
+ console.log(`[editorProxy] WebSocket upgrade: ${req.url} → ${hostname}:${port}`);
717
+ const proxySocket = net.connect(port, hostname, () => {
127
718
  // Reconstruct the HTTP upgrade request
128
719
  const requestLine = `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`;
129
720
  const headers = Object.entries(req.headers)
@@ -146,38 +737,157 @@ function handleUpgrade(req, socket, head, targetUrl) {
146
737
  proxySocket.destroy();
147
738
  });
148
739
  }
740
+ /**
741
+ * Write proxy-config.json so the preload module can discover the proxy.
742
+ */
743
+ function writeProxyConfig(proxyPort, targetUrl) {
744
+ const projectRoot = getProjectRoot() || process.env.CODEYAM_ROOT_PATH || process.cwd();
745
+ const configPath = path.join(projectRoot, '.codeyam', 'proxy-config.json');
746
+ try {
747
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
748
+ fs.writeFileSync(configPath, JSON.stringify({
749
+ proxyUrl: `http://localhost:${proxyPort}`,
750
+ devServerUrl: targetUrl,
751
+ }), 'utf-8');
752
+ console.log(`[editorProxy] Wrote proxy config to ${configPath}`);
753
+ }
754
+ catch (err) {
755
+ console.warn('[editorProxy] Failed to write proxy-config.json:', err);
756
+ }
757
+ }
758
+ /**
759
+ * Remove proxy-config.json on proxy stop.
760
+ */
761
+ function removeProxyConfig() {
762
+ const projectRoot = getProjectRoot() || process.env.CODEYAM_ROOT_PATH || process.cwd();
763
+ const configPath = path.join(projectRoot, '.codeyam', 'proxy-config.json');
764
+ try {
765
+ if (fs.existsSync(configPath)) {
766
+ fs.unlinkSync(configPath);
767
+ }
768
+ }
769
+ catch {
770
+ // Best effort
771
+ }
772
+ }
149
773
  /**
150
774
  * Start the editor proxy server.
151
- * Intercepts GET requests to API routes matching the active scenario, forwards everything else.
775
+ * Intercepts requests to API routes matching the active scenario, forwards everything else.
776
+ * Supports all HTTP methods (GET, POST, PUT, DELETE, PATCH) with body buffering.
152
777
  */
153
778
  export async function startEditorProxy(options) {
154
- // Stop existing proxy first
779
+ // If proxy is already running, reuse it (prevents second tab from killing first tab's proxy)
780
+ const existing = getProxyState();
781
+ if (existing) {
782
+ console.log(`[editorProxy] Proxy already running on port ${existing.port} → ${existing.targetUrl}`);
783
+ return { port: existing.port };
784
+ }
785
+ // Stop any leftover state (shouldn't happen, but defensive)
155
786
  await stopEditorProxy();
156
- const { targetUrl } = options;
787
+ let targetUrl = normalizeTargetUrl(options.targetUrl);
157
788
  let port = options.port;
789
+ // When the target is localhost, probe to find the correct loopback address.
790
+ // Dev servers may bind to IPv4 (127.0.0.1) or IPv6 (::1) — Vite 6 on macOS
791
+ // binds to ::1 by default. We need to match the actual binding.
792
+ try {
793
+ const parsed = new URL(targetUrl);
794
+ if (parsed.hostname === 'localhost') {
795
+ const targetPort = parseInt(parsed.port || '80', 10);
796
+ const resolvedHost = await resolveLoopbackAddress(targetPort);
797
+ if (resolvedHost) {
798
+ parsed.hostname = resolvedHost;
799
+ targetUrl = parsed.toString().replace(/\/$/, '');
800
+ console.log(`[editorProxy] Resolved localhost to ${resolvedHost} for port ${targetPort}`);
801
+ }
802
+ }
803
+ }
804
+ catch {
805
+ // Keep original targetUrl
806
+ }
158
807
  console.log(`[editorProxy] Starting proxy (requested port ${port}, target ${targetUrl})`);
808
+ const mockState = getMockStateManager();
159
809
  const server = http.createServer((req, res) => {
160
- const parsedUrl = new URL(req.url || '/', `http://localhost:${port}`);
161
- const pathname = parsedUrl.pathname;
162
- // Only intercept GET requests
163
- if (req.method === 'GET') {
164
- const scenarioData = readScenarioData();
165
- if (scenarioData) {
166
- const match = findMatchingRoute(pathname, scenarioData);
810
+ void (async () => {
811
+ const parsedUrl = new URL(req.url || '/', `http://localhost:${port}`);
812
+ const pathname = parsedUrl.pathname;
813
+ const method = req.method || 'GET';
814
+ // CORS preflight — permissive 204 for browser cross-origin requests
815
+ if (method === 'OPTIONS') {
816
+ res.writeHead(204, {
817
+ 'Access-Control-Allow-Origin': '*',
818
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
819
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
820
+ 'Access-Control-Max-Age': '86400',
821
+ });
822
+ res.end();
823
+ return;
824
+ }
825
+ // Intercept preview health reports from the injected script
826
+ if (method === 'POST' && pathname === '/__codeyam__/preview-health') {
827
+ handlePreviewHealthPost(req, res);
828
+ return;
829
+ }
830
+ // Load scenario data (also feeds MockStateManager)
831
+ readScenarioData();
832
+ // For methods that may carry a body, buffer it first
833
+ const needsBody = method === 'POST' ||
834
+ method === 'PUT' ||
835
+ method === 'DELETE' ||
836
+ method === 'PATCH';
837
+ if (needsBody) {
838
+ const bodyBuffer = await bufferRequestBody(req);
839
+ if (bodyBuffer === null) {
840
+ // Body too large — forward without mock matching
841
+ forwardBufferedRequest(req, res, targetUrl, null);
842
+ return;
843
+ }
844
+ // Try to parse body as JSON for mock matching
845
+ let parsedBody = undefined;
846
+ if (bodyBuffer.length > 0) {
847
+ try {
848
+ parsedBody = JSON.parse(bodyBuffer.toString('utf-8'));
849
+ }
850
+ catch {
851
+ // Not JSON — that's fine, still try mock matching without parsed body
852
+ }
853
+ }
854
+ const match = mockState.matchRequest(method, pathname, parsedBody);
167
855
  if (match) {
168
- console.log(`[editorProxy] Intercepted ${req.method} ${pathname} → scenario data (status ${match.status})`);
856
+ console.log(`[editorProxy] Intercepted ${method} ${pathname} → mock response (status ${match.status})`);
169
857
  res.writeHead(match.status, {
170
858
  'Content-Type': 'application/json',
171
859
  'Access-Control-Allow-Origin': '*',
172
860
  'X-CodeYam-Proxy': 'scenario-data',
861
+ 'Cache-Control': 'no-store',
173
862
  });
174
- res.end(JSON.stringify(match.body));
863
+ res.end(match.body != null ? JSON.stringify(match.body) : '');
175
864
  return;
176
865
  }
866
+ // No mock match — forward with buffered body
867
+ if ((currentScenarioType === 'application' ||
868
+ currentScenarioType === 'user') &&
869
+ pathname.startsWith('/api/')) {
870
+ mockStateEventEmitter.emitDataMutationForwarded(method, pathname);
871
+ }
872
+ forwardBufferedRequest(req, res, targetUrl, bodyBuffer);
873
+ return;
177
874
  }
178
- }
179
- // Forward everything else to the dev server
180
- forwardRequest(req, res, targetUrl);
875
+ // GET, HEAD, etc. — try mock matching (no body)
876
+ const match = mockState.matchRequest(method, pathname);
877
+ if (match) {
878
+ console.log(`[editorProxy] Intercepted ${method} ${pathname} → mock response (status ${match.status})`);
879
+ res.writeHead(match.status, {
880
+ 'Content-Type': 'application/json',
881
+ 'Access-Control-Allow-Origin': '*',
882
+ 'X-CodeYam-Proxy': 'scenario-data',
883
+ 'Cache-Control': 'no-store',
884
+ });
885
+ res.end(match.body != null ? JSON.stringify(match.body) : '');
886
+ return;
887
+ }
888
+ // Forward everything else to the dev server
889
+ forwardRequest(req, res, targetUrl);
890
+ })();
181
891
  });
182
892
  // Handle WebSocket upgrades (for HMR)
183
893
  server.on('upgrade', (req, socket, head) => {
@@ -195,9 +905,14 @@ export async function startEditorProxy(options) {
195
905
  resolve();
196
906
  });
197
907
  });
198
- port = currentPort;
908
+ // When port 0 is requested, the OS assigns an ephemeral port
909
+ const addr = server.address();
910
+ port =
911
+ typeof addr === 'object' && addr !== null ? addr.port : currentPort;
199
912
  const state = { server, port, targetUrl };
200
913
  setProxyState(state);
914
+ // Write proxy-config.json for the preload module
915
+ writeProxyConfig(port, targetUrl);
201
916
  console.log(`[editorProxy] Proxy started on port ${port}, forwarding to ${targetUrl}`);
202
917
  return { port };
203
918
  }
@@ -220,6 +935,7 @@ export async function stopEditorProxy() {
220
935
  if (!state)
221
936
  return;
222
937
  console.log(`[editorProxy] Stopping proxy on port ${state.port}`);
938
+ removeProxyConfig();
223
939
  return new Promise((resolve) => {
224
940
  state.server.close(() => {
225
941
  console.log('[editorProxy] Proxy stopped');
@@ -235,6 +951,41 @@ export async function stopEditorProxy() {
235
951
  */
236
952
  export function invalidateScenarioCache() {
237
953
  scenarioCache = { data: null, timestamp: 0 };
954
+ sessionConfig = undefined;
955
+ seedSessionCookies = undefined;
956
+ localStorageConfig = null;
957
+ activeScenarioId = null;
958
+ currentPrototypeId = null;
959
+ }
960
+ /**
961
+ * Verify that the proxy can successfully forward a request to the target dev server.
962
+ * Makes a HEAD request through the proxy and checks that it gets a response (any status).
963
+ * Returns false if the proxy isn't running or if the request fails entirely.
964
+ */
965
+ export async function verifyProxyForwarding() {
966
+ const state = getProxyState();
967
+ if (!state) {
968
+ console.warn('[editorProxy] Cannot verify — proxy is not running');
969
+ return false;
970
+ }
971
+ try {
972
+ const response = await fetch(`http://127.0.0.1:${state.port}/`, {
973
+ method: 'HEAD',
974
+ signal: AbortSignal.timeout(5000),
975
+ });
976
+ // Any response from the target (even 404) means forwarding works.
977
+ // Only 502 (our own Bad Gateway) means the target is unreachable.
978
+ if (response.status === 502) {
979
+ console.warn(`[editorProxy] Verification failed — proxy returned 502 (target unreachable)`);
980
+ return false;
981
+ }
982
+ console.log(`[editorProxy] Verification passed — proxy forwarding to ${state.targetUrl} (status ${response.status})`);
983
+ return true;
984
+ }
985
+ catch (err) {
986
+ console.warn(`[editorProxy] Verification failed — could not reach proxy on port ${state.port}`);
987
+ return false;
988
+ }
238
989
  }
239
990
  /**
240
991
  * Ensure the proxy is running. If it's not, start it using the current dev server URL.
@@ -256,9 +1007,10 @@ export async function ensureProxyRunning() {
256
1007
  return null;
257
1008
  }
258
1009
  const codeyamPort = parseInt(process.env.CODEYAM_PORT || '3111', 10);
259
- console.log(`[editorProxy] Proxy not running, starting on-demand (port ${codeyamPort + 1}, target ${devServer.url})`);
1010
+ const { proxyPort } = computeEditorPorts(codeyamPort);
1011
+ console.log(`[editorProxy] Proxy not running, starting on-demand (port ${proxyPort}, target ${devServer.url})`);
260
1012
  const result = await startEditorProxy({
261
- port: codeyamPort + 1,
1013
+ port: proxyPort,
262
1014
  targetUrl: devServer.url,
263
1015
  });
264
1016
  if (result) {
@@ -269,4 +1021,8 @@ export async function ensureProxyRunning() {
269
1021
  console.error('[editorProxy] Failed to start on-demand proxy');
270
1022
  return null;
271
1023
  }
1024
+ /**
1025
+ * Test-only export: trigger readScenarioData so tests can verify session config extraction.
1026
+ */
1027
+ export const _readScenarioDataForTest = readScenarioData;
272
1028
  //# sourceMappingURL=editorProxy.js.map