waygraph 0.15.54 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. package/README.md +8 -3
  2. package/bin/waygraph +2 -2
  3. package/dist/analysis/check.d.ts +38 -0
  4. package/dist/analysis/check.js +87 -0
  5. package/dist/analysis/coverage-gap.d.ts +1 -1
  6. package/dist/analysis/coverage-gap.js +14 -37
  7. package/dist/analysis/flow-source.d.ts +9 -0
  8. package/dist/analysis/flow-source.js +25 -0
  9. package/dist/analysis/graph.d.ts +10 -14
  10. package/dist/analysis/graph.js +48 -371
  11. package/dist/analysis/map-check.js +4 -39
  12. package/dist/analysis/practices-check.d.ts +1 -1
  13. package/dist/analysis/practices-check.js +24 -45
  14. package/dist/cli/args.d.ts +23 -0
  15. package/dist/cli/args.js +20 -0
  16. package/dist/{cli.d.ts → cli/cli.d.ts} +0 -1
  17. package/dist/{cli.js → cli/cli.js} +10 -9
  18. package/dist/{commands → cli/commands}/agent-dive-scaffold.js +35 -64
  19. package/dist/cli/commands/agent-dive.js +42 -0
  20. package/dist/cli/commands/browser.d.ts +2 -0
  21. package/dist/cli/commands/browser.js +109 -0
  22. package/dist/{commands → cli/commands}/check.d.ts +0 -1
  23. package/dist/cli/commands/check.js +104 -0
  24. package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
  25. package/dist/cli/commands/codemod-checkpoints.js +186 -0
  26. package/dist/cli/commands/codemod-flows.d.ts +18 -0
  27. package/dist/cli/commands/codemod-flows.js +284 -0
  28. package/dist/cli/commands/codemod-stubs.d.ts +10 -0
  29. package/dist/cli/commands/codemod-stubs.js +187 -0
  30. package/dist/{commands → cli/commands}/extensions.js +5 -4
  31. package/dist/{commands → cli/commands}/init.js +1 -2
  32. package/dist/{commands → cli/commands}/list.js +9 -7
  33. package/dist/cli/commands/manifest.d.ts +2 -0
  34. package/dist/cli/commands/manifest.js +20 -0
  35. package/dist/cli/commands/map.js +57 -0
  36. package/dist/cli/commands/pilot.d.ts +2 -0
  37. package/dist/cli/commands/pilot.js +102 -0
  38. package/dist/{commands → cli/commands}/run.d.ts +0 -1
  39. package/dist/cli/commands/run.js +64 -0
  40. package/dist/cli/commands/session-ops.d.ts +3 -0
  41. package/dist/cli/commands/session-ops.js +257 -0
  42. package/dist/cli/commands/session.js +132 -0
  43. package/dist/{commands → cli/commands}/test.js +11 -14
  44. package/dist/cli/commands/traverse.js +105 -0
  45. package/dist/{commands → cli/commands}/try.js +29 -25
  46. package/dist/{commands → cli/commands}/upgrade.js +40 -4
  47. package/dist/cli/flags.d.ts +193 -16
  48. package/dist/cli/flags.js +179 -234
  49. package/dist/cli/run-chain.d.ts +1 -0
  50. package/dist/cli/run-chain.js +42 -7
  51. package/dist/cli/usage.d.ts +1 -1
  52. package/dist/cli/usage.js +21 -53
  53. package/dist/cli/util.d.ts +2 -2
  54. package/dist/cli/util.js +2 -3
  55. package/dist/{highlights → demo/narration}/css.d.ts +1 -1
  56. package/dist/{highlights → demo/narration}/css.js +2 -3
  57. package/dist/{highlights → demo/narration}/demo-pace.d.ts +4 -12
  58. package/dist/{highlights → demo/narration}/demo-pace.js +5 -11
  59. package/dist/{highlights → demo/narration}/device.d.ts +4 -4
  60. package/dist/{highlights → demo/narration}/device.js +1 -1
  61. package/dist/demo/narration/merge.d.ts +10 -0
  62. package/dist/demo/narration/merge.js +67 -0
  63. package/dist/demo/narration/narration.d.ts +39 -0
  64. package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
  65. package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
  66. package/dist/demo/narration/stub-ctx.d.ts +8 -0
  67. package/dist/demo/narration/stub-ctx.js +164 -0
  68. package/dist/{highlights → demo/narration}/style.d.ts +1 -7
  69. package/dist/{highlights → demo/narration}/style.js +1 -41
  70. package/dist/{highlights → demo/narration}/todo-dock.d.ts +8 -8
  71. package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
  72. package/dist/demo/overlay/auto-chrome.d.ts +7 -0
  73. package/dist/demo/overlay/auto-chrome.js +97 -0
  74. package/dist/demo/overlay/cursor.d.ts +19 -0
  75. package/dist/demo/overlay/cursor.js +142 -0
  76. package/dist/demo/overlay/device-stage.d.ts +26 -0
  77. package/dist/demo/overlay/device-stage.js +396 -0
  78. package/dist/demo/overlay/inpage/banner.d.ts +2 -0
  79. package/dist/demo/overlay/inpage/banner.js +160 -0
  80. package/dist/demo/overlay/inpage/caption.d.ts +2 -0
  81. package/dist/demo/overlay/inpage/caption.js +24 -0
  82. package/dist/demo/overlay/inpage/core.d.ts +2 -0
  83. package/dist/demo/overlay/inpage/core.js +345 -0
  84. package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
  85. package/dist/demo/overlay/inpage/device-chip.js +191 -0
  86. package/dist/demo/overlay/inpage/network.d.ts +10 -0
  87. package/dist/demo/overlay/inpage/network.js +189 -0
  88. package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
  89. package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
  90. package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
  91. package/dist/demo/overlay/inpage/stamp.js +46 -0
  92. package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
  93. package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
  94. package/dist/demo/overlay/inpage/todos.d.ts +2 -0
  95. package/dist/demo/overlay/inpage/todos.js +293 -0
  96. package/dist/demo/overlay/locator-theater.d.ts +25 -0
  97. package/dist/demo/overlay/locator-theater.js +76 -0
  98. package/dist/demo/overlay/network-capture.d.ts +22 -0
  99. package/dist/demo/overlay/network-capture.js +127 -0
  100. package/dist/demo/overlay/overlay-css.d.ts +3 -0
  101. package/dist/demo/overlay/overlay-css.js +369 -0
  102. package/dist/demo/overlay/overlay-stage.d.ts +31 -0
  103. package/dist/demo/overlay/overlay-stage.js +106 -0
  104. package/dist/demo/overlay/overlay.d.ts +10 -0
  105. package/dist/demo/overlay/overlay.js +89 -0
  106. package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
  107. package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
  108. package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
  109. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
  110. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
  111. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
  112. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
  113. package/dist/demo/overlay/reattach.d.ts +7 -0
  114. package/dist/demo/overlay/reattach.js +23 -0
  115. package/dist/demo/overlay/rings.d.ts +61 -0
  116. package/dist/demo/overlay/rings.js +422 -0
  117. package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
  118. package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
  119. package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
  120. package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
  121. package/dist/demo/stepper/after.d.ts +3 -0
  122. package/dist/demo/stepper/after.js +103 -0
  123. package/dist/demo/stepper/banner-log.d.ts +35 -0
  124. package/dist/demo/stepper/banner-log.js +65 -0
  125. package/dist/demo/stepper/before.d.ts +4 -0
  126. package/dist/demo/stepper/before.js +110 -0
  127. package/dist/demo/stepper/demo-log.d.ts +48 -0
  128. package/dist/demo/stepper/demo-log.js +292 -0
  129. package/dist/demo/stepper/gate.d.ts +11 -0
  130. package/dist/demo/stepper/gate.js +78 -0
  131. package/dist/demo/stepper/interaction-patch.d.ts +4 -0
  132. package/dist/demo/stepper/interaction-patch.js +323 -0
  133. package/dist/demo/stepper/pacing.d.ts +21 -0
  134. package/dist/demo/stepper/pacing.js +23 -0
  135. package/dist/demo/stepper/panel-after.d.ts +17 -0
  136. package/dist/demo/stepper/panel-after.js +166 -0
  137. package/dist/demo/stepper/panel-before.d.ts +12 -0
  138. package/dist/demo/stepper/panel-before.js +241 -0
  139. package/dist/demo/stepper/slides.d.ts +23 -0
  140. package/dist/demo/stepper/slides.js +233 -0
  141. package/dist/demo/stepper/step-panels.d.ts +69 -0
  142. package/dist/demo/stepper/step-panels.js +172 -0
  143. package/dist/demo/stepper/stepper.d.ts +24 -0
  144. package/dist/demo/stepper/stepper.js +122 -0
  145. package/dist/demo/stepper/teardown.d.ts +47 -0
  146. package/dist/demo/stepper/teardown.js +178 -0
  147. package/dist/demo/stepper/todo-advance.d.ts +15 -0
  148. package/dist/demo/stepper/todo-advance.js +110 -0
  149. package/dist/demo/stepper/view.d.ts +58 -0
  150. package/dist/demo/stepper/view.js +31 -0
  151. package/dist/demo/types.d.ts +85 -0
  152. package/dist/demo/verbose-log.js +15 -0
  153. package/dist/engine/block/action-page.d.ts +53 -0
  154. package/dist/engine/block/action-page.js +1 -0
  155. package/dist/{types.d.ts → engine/block/block.d.ts} +102 -142
  156. package/dist/{core → engine/block}/block.js +12 -130
  157. package/dist/engine/block/branch.d.ts +17 -0
  158. package/dist/engine/block/branch.js +40 -0
  159. package/dist/{core → engine/block}/compose.d.ts +9 -7
  160. package/dist/{core → engine/block}/compose.js +1 -1
  161. package/dist/engine/block/dialog.d.ts +13 -0
  162. package/dist/engine/block/dialog.js +37 -0
  163. package/dist/{core/blocks → engine/block/kinds}/api.d.ts +16 -12
  164. package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
  165. package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
  166. package/dist/engine/block/kinds/effect.js +17 -0
  167. package/dist/{core/blocks → engine/block/kinds}/method.d.ts +17 -29
  168. package/dist/{core/blocks → engine/block/kinds}/method.js +6 -21
  169. package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +21 -31
  170. package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
  171. package/dist/{core/blocks → engine/block/kinds}/page.d.ts +14 -20
  172. package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
  173. package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
  174. package/dist/engine/checkpoint/checkpoint.js +8 -0
  175. package/dist/engine/checkpoint/route.d.ts +28 -0
  176. package/dist/engine/checkpoint/route.js +28 -0
  177. package/dist/{core → engine}/config.d.ts +7 -2
  178. package/dist/engine/config.js +6 -0
  179. package/dist/engine/engine.d.ts +45 -0
  180. package/dist/{core → engine}/engine.js +6 -10
  181. package/dist/engine/env.d.ts +59 -0
  182. package/dist/engine/env.js +83 -0
  183. package/dist/{errors.d.ts → engine/errors.d.ts} +22 -22
  184. package/dist/{errors.js → engine/errors.js} +22 -22
  185. package/dist/{core → engine/flow}/branch-regression.d.ts +7 -7
  186. package/dist/{core → engine/flow}/branch-regression.js +4 -3
  187. package/dist/engine/flow/flow.d.ts +162 -0
  188. package/dist/engine/flow/flow.js +244 -0
  189. package/dist/engine/flow/map-branch.d.ts +9 -0
  190. package/dist/engine/flow/map-branch.js +57 -0
  191. package/dist/{core → engine/flow}/map-builder.d.ts +34 -54
  192. package/dist/engine/flow/map-builder.js +242 -0
  193. package/dist/engine/flow/map-steps.d.ts +30 -0
  194. package/dist/engine/flow/map-steps.js +87 -0
  195. package/dist/{core → engine}/locate.d.ts +1 -1
  196. package/dist/{core → engine}/locate.js +1 -2
  197. package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
  198. package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
  199. package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
  200. package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
  201. package/dist/engine/page-gone.d.ts +5 -0
  202. package/dist/engine/page-gone.js +20 -0
  203. package/dist/engine/run/connect.d.ts +28 -0
  204. package/dist/{types.js → engine/run/connect.js} +11 -10
  205. package/dist/engine/run/events.d.ts +67 -0
  206. package/dist/engine/run/events.js +90 -0
  207. package/dist/engine/run/hooks.d.ts +16 -0
  208. package/dist/engine/run/hooks.js +8 -0
  209. package/dist/engine/run/launch.d.ts +13 -0
  210. package/dist/engine/run/launch.js +27 -0
  211. package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +8 -12
  212. package/dist/{core/run-graph.js → engine/run/run.js} +22 -12
  213. package/dist/engine/stub/pace.d.ts +12 -0
  214. package/dist/engine/stub/pace.js +2 -0
  215. package/dist/engine/stub/ring.d.ts +130 -0
  216. package/dist/engine/stub/ring.js +41 -0
  217. package/dist/engine/stub/stub.d.ts +268 -0
  218. package/dist/engine/stub/stub.js +1 -0
  219. package/dist/engine/stub/todos.d.ts +104 -0
  220. package/dist/engine/stub/todos.js +2 -0
  221. package/dist/engine/stub/viewport.d.ts +26 -0
  222. package/dist/engine/stub/viewport.js +2 -0
  223. package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
  224. package/dist/{trait.js → engine/trait/trait.js} +1 -1
  225. package/dist/index.d.ts +88 -36
  226. package/dist/index.js +46 -19
  227. package/dist/live/auto/auto.d.ts +22 -0
  228. package/dist/live/auto/auto.js +207 -0
  229. package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
  230. package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
  231. package/dist/live/auto/mem.d.ts +11 -0
  232. package/dist/live/auto/mem.js +85 -0
  233. package/dist/live/auto/menu.d.ts +30 -0
  234. package/dist/live/auto/menu.js +335 -0
  235. package/dist/live/auto-session/auto-session.d.ts +113 -0
  236. package/dist/live/auto-session/auto-session.js +452 -0
  237. package/dist/live/auto-session/console.d.ts +4 -0
  238. package/dist/live/auto-session/console.js +41 -0
  239. package/dist/live/auto-session/files.d.ts +44 -0
  240. package/dist/live/auto-session/files.js +145 -0
  241. package/dist/{auto-session → live/auto-session}/helpers.d.ts +9 -5
  242. package/dist/{auto-session → live/auto-session}/helpers.js +18 -1
  243. package/dist/live/auto-session/inspect.d.ts +4 -0
  244. package/dist/live/auto-session/inspect.js +75 -0
  245. package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +8 -25
  246. package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +36 -161
  247. package/dist/live/auto-session/open-browser.d.ts +6 -0
  248. package/dist/live/auto-session/open-browser.js +47 -0
  249. package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
  250. package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
  251. package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
  252. package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
  253. package/dist/{session → live/pilot}/pilot.d.ts +3 -3
  254. package/dist/{session → live/pilot}/pilot.js +5 -4
  255. package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +1 -1
  256. package/dist/live/traverse/traverse.js +212 -0
  257. package/dist/live/traverse/worker.d.ts +37 -0
  258. package/dist/live/traverse/worker.js +200 -0
  259. package/dist/manifest/manifest.d.ts +52 -0
  260. package/dist/manifest/manifest.js +93 -0
  261. package/dist/manifest/map-imports.d.ts +7 -0
  262. package/dist/manifest/map-imports.js +22 -0
  263. package/dist/manifest/maps.d.ts +33 -0
  264. package/dist/manifest/maps.js +62 -0
  265. package/dist/manifest/pack.d.ts +21 -0
  266. package/dist/manifest/pack.js +109 -0
  267. package/dist/manifest/project.d.ts +60 -0
  268. package/dist/manifest/project.js +101 -0
  269. package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
  270. package/dist/manifest/scan.d.ts +19 -0
  271. package/dist/manifest/scan.js +57 -0
  272. package/dist/manifest/source.d.ts +23 -0
  273. package/dist/manifest/source.js +86 -0
  274. package/dist/runner/mode.d.ts +71 -0
  275. package/dist/runner/mode.js +1 -0
  276. package/dist/runner/modes/branches.d.ts +5 -0
  277. package/dist/runner/modes/branches.js +37 -0
  278. package/dist/runner/modes/demo.d.ts +3 -0
  279. package/dist/runner/modes/demo.js +13 -0
  280. package/dist/runner/modes/report.d.ts +2 -0
  281. package/dist/runner/modes/report.js +54 -0
  282. package/dist/runner/modes/run.d.ts +2 -0
  283. package/dist/runner/modes/run.js +3 -0
  284. package/dist/runner/options.d.ts +31 -0
  285. package/dist/runner/options.js +42 -0
  286. package/dist/runner/plan/find.d.ts +18 -0
  287. package/dist/runner/plan/find.js +65 -0
  288. package/dist/runner/plan/plan.d.ts +11 -0
  289. package/dist/runner/plan/plan.js +97 -0
  290. package/dist/runner/plan/seed-mem.d.ts +12 -0
  291. package/dist/runner/plan/seed-mem.js +98 -0
  292. package/dist/runner/plan/spec.d.ts +5 -0
  293. package/dist/runner/plan/spec.js +17 -0
  294. package/dist/runner/play-steps.d.ts +2 -0
  295. package/dist/runner/play-steps.js +59 -0
  296. package/dist/runner/runner.d.ts +4 -0
  297. package/dist/runner/runner.js +64 -0
  298. package/dist/runner/session.d.ts +9 -0
  299. package/dist/runner/session.js +87 -0
  300. package/dist/{browser.js → runtime/browser.js} +4 -2
  301. package/dist/{env-file.js → runtime/env-file.js} +7 -12
  302. package/dist/{extensions.d.ts → runtime/extensions.d.ts} +1 -5
  303. package/dist/{extensions.js → runtime/extensions.js} +2 -1
  304. package/dist/runtime/full-launch.d.ts +1 -0
  305. package/dist/runtime/full-launch.js +34 -0
  306. package/dist/runtime/global-flag.d.ts +5 -0
  307. package/dist/runtime/global-flag.js +18 -0
  308. package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
  309. package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
  310. package/dist/runtime/run-log.d.ts +2 -0
  311. package/dist/runtime/run-log.js +17 -0
  312. package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
  313. package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +6 -9
  314. package/dist/{config.js → runtime/waygraph-config.js} +21 -51
  315. package/dist/{webserver.js → runtime/webserver.js} +5 -30
  316. package/examples/routed-demo/config/waygraph.config.ts +20 -0
  317. package/examples/routed-demo/package.json +1 -4
  318. package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
  319. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
  320. package/examples/routed-demo/src/flows/routed-demo.flow.ts +1 -2
  321. package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
  322. package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
  323. package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
  324. package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
  325. package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
  326. package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
  327. package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
  328. package/examples/routed-demo/tsconfig.json +1 -1
  329. package/examples/saucedemo/docs/CONVENTION.md +4 -5
  330. package/examples/saucedemo/docs/HELPERS.md +11 -11
  331. package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
  332. package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
  333. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
  334. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  335. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  336. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  337. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  338. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  339. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
  340. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
  341. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  342. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
  343. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  344. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  345. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  346. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  347. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  348. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  349. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
  350. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
  351. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
  352. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  353. package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  354. package/examples/saucedemo/src/flows/api-demo.flow.ts +12 -10
  355. package/examples/saucedemo/src/states/checkout.states.ts +21 -11
  356. package/examples/saucedemo/src/stubs/device-showcase.ts +8 -10
  357. package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
  358. package/package.json +14 -6
  359. package/templates/agents/waygraph-planner.agent.md +2 -2
  360. package/templates/quickstart/docs/CONVENTION.md +4 -4
  361. package/templates/quickstart/docs/HELPERS.md +10 -8
  362. package/templates/quickstart/package.json +0 -3
  363. package/templates/quickstart/src/blocks/SITE-MAP.md +0 -1
  364. package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
  365. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
  366. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  367. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  368. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  369. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  370. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  371. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
  372. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
  373. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  374. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
  375. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  376. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  377. package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  378. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  379. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  380. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  381. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
  382. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
  383. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
  384. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  385. package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  386. package/templates/quickstart/src/flows/api-demo.flow.ts +12 -10
  387. package/templates/quickstart/src/states/checkout.states.ts +21 -11
  388. package/templates/quickstart/src/stubs/device-showcase.ts +8 -10
  389. package/templates/scaffold/README.md +2 -1
  390. package/templates/scaffold/STRUCTURE.md +5 -4
  391. package/templates/scaffold/config/waygraph.config.ts +1 -0
  392. package/templates/scaffold/gitignore +1 -0
  393. package/templates/scaffold/src/flows/README.md +2 -2
  394. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
  395. package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
  396. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
  397. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
  398. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
  399. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
  400. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
  401. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
  402. package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
  403. package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
  404. package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
  405. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
  406. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
  407. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
  408. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
  409. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
  410. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
  411. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
  412. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
  413. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
  414. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
  415. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
  416. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
  417. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
  418. package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
  419. package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
  420. package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
  421. package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
  422. package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
  423. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
  424. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
  425. package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
  426. package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
  427. package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
  428. package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
  429. package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
  430. package/templates/scaffold/src/map/README.md +7 -0
  431. package/templates/scaffold/src/states/README.md +4 -1
  432. package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
  433. package/templates/scaffold/src/states/demo.states.ts +14 -20
  434. package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
  435. package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
  436. package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
  437. package/templates/skills/waygraph-convention.skill.md +23 -14
  438. package/templates/skills/waygraph-pilot.skill.md +7 -4
  439. package/dist/auto-session/session.d.ts +0 -193
  440. package/dist/auto-session/session.js +0 -719
  441. package/dist/auto-session/verbose-log.js +0 -16
  442. package/dist/auto-session.d.ts +0 -2
  443. package/dist/auto-session.js +0 -3
  444. package/dist/cli/discover.d.ts +0 -40
  445. package/dist/cli/discover.js +0 -148
  446. package/dist/commands/agent-dive.js +0 -52
  447. package/dist/commands/check.js +0 -192
  448. package/dist/commands/map.js +0 -29
  449. package/dist/commands/run.js +0 -104
  450. package/dist/commands/session.js +0 -600
  451. package/dist/commands/traverse.js +0 -177
  452. package/dist/core/block.d.ts +0 -109
  453. package/dist/core/blocks/effect.js +0 -23
  454. package/dist/core/config.js +0 -17
  455. package/dist/core/engine.d.ts +0 -198
  456. package/dist/core/flow.d.ts +0 -294
  457. package/dist/core/flow.js +0 -432
  458. package/dist/core/map-builder.js +0 -383
  459. package/dist/core.d.ts +0 -14
  460. package/dist/core.js +0 -15
  461. package/dist/highlights/merge.d.ts +0 -8
  462. package/dist/highlights/merge.js +0 -173
  463. package/dist/highlights/run-phase.d.ts +0 -43
  464. package/dist/highlights/stub-ctx.d.ts +0 -10
  465. package/dist/highlights/stub-ctx.js +0 -331
  466. package/dist/highlights/types.d.ts +0 -613
  467. package/dist/highlights.d.ts +0 -9
  468. package/dist/highlights.js +0 -10
  469. package/dist/pilot-overlay.d.ts +0 -5
  470. package/dist/pilot-overlay.js +0 -6
  471. package/dist/runner/banner-log.js +0 -63
  472. package/dist/runner/chain-run.js +0 -102
  473. package/dist/runner/cursor.js +0 -140
  474. package/dist/runner/demo-log.js +0 -316
  475. package/dist/runner/device-stage.d.ts +0 -9
  476. package/dist/runner/device-stage.js +0 -420
  477. package/dist/runner/discovery.js +0 -105
  478. package/dist/runner/index.js +0 -2
  479. package/dist/runner/inpage/banner.d.ts +0 -21
  480. package/dist/runner/inpage/banner.js +0 -156
  481. package/dist/runner/inpage/caption.d.ts +0 -3
  482. package/dist/runner/inpage/caption.js +0 -23
  483. package/dist/runner/inpage/core.d.ts +0 -4
  484. package/dist/runner/inpage/core.js +0 -316
  485. package/dist/runner/inpage/device.d.ts +0 -3
  486. package/dist/runner/inpage/device.js +0 -211
  487. package/dist/runner/inpage/network.d.ts +0 -15
  488. package/dist/runner/inpage/network.js +0 -217
  489. package/dist/runner/inpage/panel-chrome.js +0 -192
  490. package/dist/runner/inpage/stamp.js +0 -46
  491. package/dist/runner/inpage/swipe-zoom.js +0 -220
  492. package/dist/runner/inpage/todos.js +0 -337
  493. package/dist/runner/interaction-patch.js +0 -384
  494. package/dist/runner/main.js +0 -469
  495. package/dist/runner/network-capture.d.ts +0 -9
  496. package/dist/runner/network-capture.js +0 -126
  497. package/dist/runner/overlay-css.d.ts +0 -3
  498. package/dist/runner/overlay-css.js +0 -377
  499. package/dist/runner/overlay-install.js +0 -90
  500. package/dist/runner/overlay-stage.js +0 -110
  501. package/dist/runner/rings.js +0 -514
  502. package/dist/runner/seed-mem.js +0 -110
  503. package/dist/runner/slides.js +0 -278
  504. package/dist/runner/step-mode.js +0 -703
  505. package/dist/runner/step-panels.js +0 -729
  506. package/dist/runner/teardown.js +0 -202
  507. package/dist/runner/todo-dock.js +0 -142
  508. package/dist/session/auto-explore-run.d.ts +0 -40
  509. package/dist/session/auto-explore-run.js +0 -707
  510. package/dist/session/step-overlay.d.ts +0 -37
  511. package/dist/session/step-overlay.js +0 -244
  512. package/dist/traverse/run.js +0 -423
  513. package/examples/routed-demo/playwright.config.ts +0 -21
  514. package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  515. package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  516. /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
  517. /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
  518. /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
  519. /package/dist/{commands → cli/commands}/init.d.ts +0 -0
  520. /package/dist/{commands → cli/commands}/list.d.ts +0 -0
  521. /package/dist/{commands → cli/commands}/map.d.ts +0 -0
  522. /package/dist/{commands → cli/commands}/session.d.ts +0 -0
  523. /package/dist/{commands → cli/commands}/test.d.ts +0 -0
  524. /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
  525. /package/dist/{commands → cli/commands}/try.d.ts +0 -0
  526. /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
  527. /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
  528. /package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +0 -0
  529. /package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +0 -0
  530. /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
  531. /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
  532. /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
  533. /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
  534. /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
  535. /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
  536. /package/dist/{highlights → demo}/types.js +0 -0
  537. /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
  538. /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
  539. /package/dist/{selector.js → engine/trait/selector.js} +0 -0
  540. /package/dist/{traverse → live/traverse}/coverage.d.ts +0 -0
  541. /package/dist/{traverse → live/traverse}/coverage.js +0 -0
  542. /package/dist/{traverse → live/traverse}/lease.d.ts +0 -0
  543. /package/dist/{traverse → live/traverse}/lease.js +0 -0
  544. /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
  545. /package/dist/{blocks-select.d.ts → manifest/select.d.ts} +0 -0
  546. /package/dist/{blocks-select.js → manifest/select.js} +0 -0
  547. /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
  548. /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
  549. /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
  550. /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
  551. /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
  552. /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
@@ -0,0 +1,186 @@
1
+ // `waygraph upgrade --codemod checkpoints`: rewrites a project from tag strings and `<In, Out>` type arguments to
2
+ // Checkpoint values (`export const Home = checkpoint("Home")`, `checkpoint: Home`, `from: Home, to: ItemInCart`). Works
3
+ // on the TypeScript AST (ts-morph), so formatting, comments and odd line breaks don't fool it.
4
+ import { readFileSync, writeFileSync } from "node:fs";
5
+ import { relative } from "node:path";
6
+ import { IndentationText, Node, Project, SyntaxKind } from "ts-morph";
7
+ import { walkDir } from "../../manifest/scan.js";
8
+ function parse(text) {
9
+ const indentationText = /\n\t/.test(text) ? IndentationText.Tab : /\n {4}\S/.test(text) && !/\n {2}\S/.test(text) ? IndentationText.FourSpaces : IndentationText.TwoSpaces;
10
+ return new Project({ useInMemoryFileSystem: true, manipulationSettings: { indentationText } }).createSourceFile("/file.ts", text);
11
+ }
12
+ /** Whether `name` is still used anywhere outside import statements. */
13
+ function usedOutsideImports(sf, name) {
14
+ return sf.getDescendantsOfKind(SyntaxKind.Identifier).some((id) => {
15
+ if (id.getText() !== name || id.getFirstAncestorByKind(SyntaxKind.ImportDeclaration))
16
+ return false;
17
+ const parent = id.getParent();
18
+ return !(Node.isPropertyAccessExpression(parent) && parent.getNameNode() === id) && !(Node.isPropertyAssignment(parent) && parent.getNameNode() === id);
19
+ });
20
+ }
21
+ /** Drops a named import from "waygraph" that nothing uses any more (and the import, when it ends up empty). */
22
+ function dropUnusedWaygraphImport(sf, name) {
23
+ if (usedOutsideImports(sf, name))
24
+ return;
25
+ for (const imp of sf.getImportDeclarations().filter((d) => d.getModuleSpecifierValue() === "waygraph")) {
26
+ imp.getNamedImports().find((n) => n.getName() === name)?.remove();
27
+ if (imp.getNamedImports().length === 0 && !imp.getDefaultImport() && !imp.getNamespaceImport())
28
+ imp.remove();
29
+ }
30
+ }
31
+ /** Learns Checkpoint declarations already in value form, so the codemod can run again after a partial run. */
32
+ function learnValues(sf, info) {
33
+ for (const decl of sf.getVariableDeclarations()) {
34
+ const init = decl.getInitializer();
35
+ if (Node.isCallExpression(init) && init.getExpression().getText() === "checkpoint") {
36
+ const tag = init.getArguments()[0];
37
+ if (Node.isStringLiteral(tag))
38
+ info.tags.set(decl.getName(), tag.getLiteralValue());
39
+ }
40
+ else if (Node.isAsExpression(init) && Node.isArrayLiteralExpression(init.getExpression())) {
41
+ info.unions.set(decl.getName(), init.getExpression().asKindOrThrow(SyntaxKind.ArrayLiteralExpression).getElements().map((e) => e.getText()));
42
+ }
43
+ }
44
+ }
45
+ /** Rewrites one states file; returns the new text and what it declared. */
46
+ export function convertStates(text, info) {
47
+ const sf = parse(text);
48
+ learnValues(sf, info);
49
+ let changed = false;
50
+ for (const alias of sf.getTypeAliases()) {
51
+ if (!alias.isExported())
52
+ continue;
53
+ const name = alias.getName();
54
+ const type = alias.getTypeNodeOrThrow();
55
+ if (Node.isTypeReference(type) && type.getTypeName().getText() === "Checkpoint") {
56
+ const arg = type.getTypeArguments()[0];
57
+ if (!Node.isLiteralTypeNode(arg) || !Node.isStringLiteral(arg.getLiteral()))
58
+ continue;
59
+ const tag = arg.getLiteral().asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
60
+ info.tags.set(name, tag);
61
+ alias.replaceWithText(`export const ${name} = checkpoint("${tag}");\nexport type ${name} = typeof ${name};`);
62
+ changed = true;
63
+ }
64
+ else if (Node.isUnionTypeNode(type)) {
65
+ const names = type.getTypeNodes().map((t) => t.getText());
66
+ if (!names.every((n) => info.tags.has(n) || info.unions.has(n)))
67
+ continue;
68
+ const flat = names.flatMap((n) => info.unions.get(n) ?? [n]);
69
+ info.unions.set(name, flat);
70
+ alias.replaceWithText(`export const ${name} = [${flat.join(", ")}] as const;\nexport type ${name} = (typeof ${name})[number];`);
71
+ changed = true;
72
+ }
73
+ }
74
+ if (!changed)
75
+ return text;
76
+ // `checkpoint` is now used as a value; `Checkpoint` stays only while something still names the type.
77
+ const wg = sf.getImportDeclarations().find((d) => d.getModuleSpecifierValue() === "waygraph");
78
+ if (!wg)
79
+ sf.insertImportDeclaration(0, { moduleSpecifier: "waygraph", namedImports: ["checkpoint"] });
80
+ else if (wg.isTypeOnly())
81
+ sf.insertImportDeclaration(wg.getChildIndex(), { moduleSpecifier: "waygraph", namedImports: ["checkpoint"] });
82
+ else if (!wg.getNamedImports().some((n) => n.getName() === "checkpoint"))
83
+ wg.addNamedImport("checkpoint");
84
+ dropUnusedWaygraphImport(sf, "Checkpoint");
85
+ return sf.getFullText();
86
+ }
87
+ const SINGLE_CHECKPOINT = ["defineNavBlock", "defineNavClickBlock", "defineMemNavBlock", "definePageBlock", "defineAssertBlock"];
88
+ const ROUTED = ["defineMethodBlock", "defineEffectBlock"];
89
+ function optionsOf(call) {
90
+ const arg = call.getArguments()[0];
91
+ return Node.isObjectLiteralExpression(arg) ? arg : undefined;
92
+ }
93
+ /** `checkpoint: "Home"` with `<Home>` becomes `checkpoint: Home`. */
94
+ function convertSingle(call, fn, info, skipped) {
95
+ const typeArg = call.getTypeArguments()[0];
96
+ const prop = optionsOf(call)?.getProperty("checkpoint");
97
+ const value = Node.isPropertyAssignment(prop) ? prop.getInitializer() : undefined;
98
+ if (!typeArg || !Node.isPropertyAssignment(prop) || !Node.isStringLiteral(value))
99
+ return;
100
+ const name = typeArg.getText();
101
+ if (info.tags.get(name) !== value.getLiteralValue()) {
102
+ skipped.push(`${fn}<${name}>`);
103
+ return;
104
+ }
105
+ call.removeTypeArgument(typeArg);
106
+ prop.setInitializer(name);
107
+ }
108
+ /** `<In, Out>` becomes `from: In, to: Out` (right after the name and description); a resolve that only returns `to` goes. */
109
+ function convertRouted(call, fn, info, skipped) {
110
+ const [fromArg, toArg] = call.getTypeArguments();
111
+ const options = optionsOf(call);
112
+ if (!fromArg || !toArg || !options)
113
+ return;
114
+ const from = fromArg.getText();
115
+ const to = toArg.getText();
116
+ const known = (n) => info.tags.has(n) || info.unions.has(n);
117
+ const anywhere = from === "Checkpoint<string>";
118
+ if ((!anywhere && !known(from)) || !known(to)) {
119
+ skipped.push(`${fn}<${from}, ${to}>`);
120
+ return;
121
+ }
122
+ call.removeTypeArgument(toArg);
123
+ call.removeTypeArgument(fromArg);
124
+ const props = options.getProperties();
125
+ const after = Math.max(...["name", "description"].map((n) => props.findIndex((p) => Node.isPropertyAssignment(p) && p.getName() === n)));
126
+ options.insertPropertyAssignments(after + 1, [...(anywhere ? [] : [{ name: "from", initializer: from }]), { name: "to", initializer: to }]);
127
+ const tag = info.tags.get(to);
128
+ const instruction = options.getProperty("instruction");
129
+ const body = Node.isPropertyAssignment(instruction) ? instruction.getInitializer() : undefined;
130
+ const resolve = Node.isObjectLiteralExpression(body) ? body.getProperty("resolve") : undefined;
131
+ if (tag && Node.isPropertyAssignment(resolve) && resolve.getInitializer()?.getText().replace(/\s/g, "") === `()=>checkpoint("${tag}")`)
132
+ resolve.remove();
133
+ // Inserting and removing properties leaves the object's indentation uneven; tidy just this call.
134
+ call.formatText({ indentSize: call.getSourceFile().getProject().manipulationSettings.getIndentationText().length, convertTabsToSpaces: !call.getSourceFile().getFullText().includes("\n\t") });
135
+ }
136
+ /** Rewrites one Block file. Calls whose Checkpoints are not plain declared names are left as they are. */
137
+ export function convertBlocks(text, info) {
138
+ const sf = parse(text);
139
+ const skipped = [];
140
+ for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression).reverse()) {
141
+ if (call.wasForgotten())
142
+ continue;
143
+ const fn = call.getExpression().getText();
144
+ if (SINGLE_CHECKPOINT.includes(fn))
145
+ convertSingle(call, fn, info, skipped);
146
+ else if (ROUTED.includes(fn))
147
+ convertRouted(call, fn, info, skipped);
148
+ }
149
+ if (sf.getFullText() === text)
150
+ return { text, skipped };
151
+ dropUnusedWaygraphImport(sf, "Checkpoint");
152
+ dropUnusedWaygraphImport(sf, "checkpoint");
153
+ // Checkpoints are now used as values: import them as values.
154
+ const known = (n) => info.tags.has(n) || info.unions.has(n);
155
+ for (const imp of sf.getImportDeclarations()) {
156
+ if (imp.isTypeOnly() && /states/.test(imp.getModuleSpecifierValue()) && imp.getNamedImports().some((n) => known(n.getName())))
157
+ imp.setIsTypeOnly(false);
158
+ }
159
+ return { text: sf.getFullText(), skipped };
160
+ }
161
+ /** Runs the codemod over a project; returns the files changed and the calls it left alone. */
162
+ export function codemodCheckpoints(projectDir) {
163
+ const info = { tags: new Map(), unions: new Map() };
164
+ const files = walkDir(projectDir, /\.ts$/).filter((f) => !f.endsWith(".d.ts"));
165
+ const states = files.filter((f) => /\.states\.ts$|[/\\]_states\.ts$/.test(f));
166
+ const changed = [];
167
+ const skipped = [];
168
+ for (const f of states) {
169
+ const before = readFileSync(f, "utf8");
170
+ const after = convertStates(before, info);
171
+ if (after !== before) {
172
+ writeFileSync(f, after);
173
+ changed.push(relative(projectDir, f));
174
+ }
175
+ }
176
+ for (const f of files.filter((x) => !states.includes(x))) {
177
+ const before = readFileSync(f, "utf8");
178
+ const { text, skipped: s } = convertBlocks(before, info);
179
+ skipped.push(...s.map((c) => `${relative(projectDir, f)}: ${c}`));
180
+ if (text !== before) {
181
+ writeFileSync(f, text);
182
+ changed.push(relative(projectDir, f));
183
+ }
184
+ }
185
+ return { changed, skipped };
186
+ }
@@ -0,0 +1,18 @@
1
+ import { Project } from "ts-morph";
2
+ import type { SourceFile } from "ts-morph";
3
+ /** A Block's kind by the file and export it is declared in; undefined when it isn't a known Block. */
4
+ export type KindOf = (file: string, exportName: string) => string | undefined;
5
+ /** Rewrites the old flow forms in a project's source files; returns problems it left for a person. */
6
+ export declare function convertFlows(project: Project, kindOf: KindOf): {
7
+ changed: SourceFile[];
8
+ problems: {
9
+ file: string;
10
+ line: number;
11
+ reason: string;
12
+ }[];
13
+ };
14
+ /** Runs the codemod over a project's TypeScript files, using its runtime scan for each Block's kind. */
15
+ export declare function codemodFlows(projectDir: string): Promise<{
16
+ changed: string[];
17
+ problems: string[];
18
+ }>;
@@ -0,0 +1,284 @@
1
+ // `waygraph upgrade --codemod flows`: rewrites `defineFlow([start, ...Blocks, end], options)`, `chainFlow(...)` and the
2
+ // flow wrappers (`withTitle`, `withMemStub`, `withSessionReset`, `withExpectedFailure`, `withDemoPace`,
3
+ // `withHighlightStyle`, `withBlockPace`, `withStub*`) into `map()` chains. Works on the TypeScript AST (ts-morph); each
4
+ // Block's kind (nav, method, assert, ...) comes from the project's own runtime scan, so it picks the right step method.
5
+ // The same pass moves ctx stubs onto their one form (codemod-stubs.ts).
6
+ import { existsSync } from "node:fs";
7
+ import { join, relative } from "node:path";
8
+ import { Node, Project, SyntaxKind } from "ts-morph";
9
+ import { scanProject } from "../../manifest/project.js";
10
+ import { walkDir } from "../../manifest/scan.js";
11
+ import { convertStubs } from "./codemod-stubs.js";
12
+ const SETTINGS = {
13
+ withMemStub: () => "memStub: true",
14
+ withSessionReset: () => "sessionReset: true",
15
+ withExpectedFailure: (a) => `expectedFailure: ${a}`,
16
+ withDemoPace: (a) => `demoPace: ${a}`,
17
+ withHighlightStyle: (a) => `highlightStyle: ${a}`,
18
+ };
19
+ const STUBS = { withStubBefore: "stubBefore", withStubAfter: "stubAfter", withStubOnError: "stubOnError" };
20
+ const REMOVED = new Set(["start", "end", "chainFlow", "withTitle", "withBlockPace", "withHighlightFixtures", ...Object.keys(SETTINGS), ...Object.keys(STUBS)]);
21
+ const STEP = { nav: "gotoPage", page: "gotoPage", method: "method", effect: "method", api: "method", assert: "assert" };
22
+ /** The Block identifier an element of a flow is built from: `X`, `X.stubBefore(...)`, `withVerify(X, ...)`. */
23
+ function rootIdentifier(expr) {
24
+ if (Node.isIdentifier(expr))
25
+ return expr;
26
+ if (Node.isCallExpression(expr)) {
27
+ const callee = expr.getExpression();
28
+ if (Node.isPropertyAccessExpression(callee))
29
+ return rootIdentifier(callee.getExpression());
30
+ if (Node.isIdentifier(callee) && callee.getText() === "withVerify")
31
+ return expr.getArguments()[0] && rootIdentifier(expr.getArguments()[0]);
32
+ }
33
+ return undefined;
34
+ }
35
+ /** Where an identifier is declared: its file and exported name, following imports. */
36
+ function declarationOf(id) {
37
+ let symbol = id.getSymbol();
38
+ if (!symbol)
39
+ return undefined;
40
+ if (symbol.isAlias())
41
+ symbol = symbol.getAliasedSymbol() ?? symbol;
42
+ const decl = symbol.getDeclarations()[0];
43
+ if (!decl)
44
+ return undefined;
45
+ return { file: decl.getSourceFile().getFilePath(), name: symbol.getName() };
46
+ }
47
+ /** `engine.map({...}).start()...end()`: the `.map(...)` call at the root of a chain, or undefined. */
48
+ function mapCallOf(expr) {
49
+ let cur = expr;
50
+ while (Node.isCallExpression(cur)) {
51
+ const callee = cur.getExpression();
52
+ if (!Node.isPropertyAccessExpression(callee))
53
+ return undefined;
54
+ if (callee.getName() === "map")
55
+ return cur;
56
+ cur = callee.getExpression();
57
+ }
58
+ return undefined;
59
+ }
60
+ /** The first step call after `.map(...)`/`.start()` in a chain. */
61
+ function firstStepOf(mapCall) {
62
+ let parent = mapCall.getParent();
63
+ while (parent && Node.isPropertyAccessExpression(parent)) {
64
+ const call = parent.getParent();
65
+ if (!call || !Node.isCallExpression(call))
66
+ return undefined;
67
+ if (parent.getName() !== "start")
68
+ return call;
69
+ parent = call.getParent();
70
+ }
71
+ return undefined;
72
+ }
73
+ function addSetting(mapCall, setting) {
74
+ const arg = mapCall.getArguments()[0];
75
+ if (arg && Node.isObjectLiteralExpression(arg)) {
76
+ const inner = arg.getText().slice(1, -1).trim().replace(/,$/, "");
77
+ arg.replaceWithText(`{ ${inner ? `${inner}, ` : ""}${setting} }`);
78
+ }
79
+ else if (!arg) {
80
+ mapCall.addArgument(`{ ${setting} }`);
81
+ }
82
+ else {
83
+ arg.replaceWithText(`{ ...${arg.getText()}, ${setting} }`);
84
+ }
85
+ }
86
+ function addTitle(step, title) {
87
+ const block = step.getArguments()[0];
88
+ if (block)
89
+ block.replaceWithText(titleStub(block.getText(), title, indentOf(step)));
90
+ }
91
+ /** `engine` when the file has one in scope, else the standalone `map` export (imported from waygraph). */
92
+ function mapRoot(sf, needsMap) {
93
+ const hasEngine = sf.getImportDeclarations().some((d) => d.getNamedImports().some((n) => (n.getAliasNode()?.getText() ?? n.getName()) === "engine"))
94
+ || sf.getVariableDeclaration("engine") !== undefined;
95
+ if (hasEngine)
96
+ return "engine.map";
97
+ needsMap.add(sf);
98
+ return "map";
99
+ }
100
+ /** The indentation of the statement a node sits in, so a rewritten chain lines up with the code around it. */
101
+ function indentOf(node) {
102
+ const statement = node.getFirstAncestor((a) => Node.isStatement(a) || Node.isSourceFile(a.getParentOrThrow())) ?? node;
103
+ return " ".repeat(statement.getIndentationLevel() * 2);
104
+ }
105
+ function titleStub(block, title, indent) {
106
+ return `${block}.stubBefore((ctx) => {\n${indent} ctx.title(${title});\n${indent} })`;
107
+ }
108
+ function chain(head, steps, indent) {
109
+ return [head, ...steps, ".end()"].join(`\n${indent} `);
110
+ }
111
+ /** Rewrites one call if it is one of the old forms; returns a problem message when it can't. */
112
+ function rewrite(call, kindOf, needsMap) {
113
+ const sf = call.getSourceFile();
114
+ const callee = call.getExpression();
115
+ const args = call.getArguments();
116
+ const name = Node.isIdentifier(callee) ? callee.getText() : undefined;
117
+ const indent = indentOf(call);
118
+ if (Node.isPropertyAccessExpression(callee) && callee.getName() === "defineFlow") {
119
+ const list = args[0];
120
+ if (!list || !Node.isArrayLiteralExpression(list))
121
+ return "defineFlow without an array literal";
122
+ const elements = list.getElements().filter((e) => e.getText() !== "start" && e.getText() !== "end");
123
+ const steps = [];
124
+ for (const el of elements) {
125
+ let block = el;
126
+ let opts = "";
127
+ if (Node.isCallExpression(el) && el.getExpression().getText() === "withBlockPace") {
128
+ block = el.getArguments()[0];
129
+ opts = `, { pace: ${el.getArguments()[1]?.getText()} }`;
130
+ }
131
+ const id = rootIdentifier(block);
132
+ const decl = id && declarationOf(id);
133
+ const kind = decl && kindOf(decl.file, decl.name);
134
+ const step = kind && STEP[kind];
135
+ if (!step)
136
+ return `${el.getText().split("\n")[0]} is not a Block from a define*Block factory (kind: ${kind ?? "unknown"}); map() can't take it - rebuild it with a factory or nest it with .flow()`;
137
+ const external = step === "gotoPage" && /[\\/]\(external\)[\\/]/.test(decl.file);
138
+ steps.push(`.${external ? "gotoExternal" : step}(${block.getText()}${opts})`);
139
+ }
140
+ const options = args[1];
141
+ let settings = "";
142
+ let title;
143
+ if (options) {
144
+ if (!Node.isObjectLiteralExpression(options))
145
+ return "defineFlow options that aren't an object literal";
146
+ const kept = [];
147
+ for (const p of options.getProperties()) {
148
+ if (Node.isPropertyAssignment(p) && p.getName() === "title")
149
+ title = p.getInitializer().getText();
150
+ else
151
+ kept.push(p.getText());
152
+ }
153
+ if (kept.length)
154
+ settings = `{ ${kept.join(", ")} }`;
155
+ }
156
+ if (title && steps[0])
157
+ steps[0] = steps[0].replace(/^(\.\w+\()(.*)\)$/s, (_all, head, block) => `${head}${titleStub(block, title, indent)})`);
158
+ call.replaceWithText(chain(`${callee.getExpression().getText()}.map(${settings})`, [".start()", ...steps], indent));
159
+ return "changed";
160
+ }
161
+ if (name === "chainFlow") {
162
+ call.replaceWithText(chain(`${mapRoot(sf, needsMap)}()`, [".start()", ...args.map((a) => `.flow(${a.getText()})`)], indent));
163
+ return "changed";
164
+ }
165
+ if (name && STUBS[name] && args.length === 2) {
166
+ call.replaceWithText(`${args[0].getText()}.${STUBS[name]}(${args[1].getText()})`);
167
+ return "changed";
168
+ }
169
+ if (name && (SETTINGS[name] || name === "withTitle") && args[0]) {
170
+ const flow = args[0];
171
+ const mapCall = mapCallOf(flow);
172
+ if (name === "withTitle") {
173
+ const first = mapCall && firstStepOf(mapCall);
174
+ if (!first)
175
+ return `withTitle(${flow.getText().split("\n")[0]}, …): name the flow with ctx.title(…) in a stub on its first step`;
176
+ addTitle(first, args[1].getText());
177
+ }
178
+ else if (mapCall) {
179
+ addSetting(mapCall, SETTINGS[name](args[1]?.getText()));
180
+ }
181
+ else {
182
+ call.replaceWithText(chain(`${mapRoot(sf, needsMap)}({ ${SETTINGS[name](args[1]?.getText())} })`, [".start()", `.flow(${flow.getText()})`], indent));
183
+ return "changed";
184
+ }
185
+ call.replaceWithText(flow.getText());
186
+ return "changed";
187
+ }
188
+ if (name === "withHighlightFixtures")
189
+ return "withHighlightFixtures: chain ctx stubs on each Block where the flow uses it (Block.stubAfter((ctx) => …))";
190
+ if (name === "withBlockPace")
191
+ return "withBlockPace outside a flow: use the step option .method(Block, { pace })";
192
+ if (Node.isPropertyAccessExpression(callee) && callee.getName() === "end" && args[0] && mapCallOf(call)) {
193
+ const options = args[0];
194
+ if (Node.isObjectLiteralExpression(options)) {
195
+ const mapCall = mapCallOf(call);
196
+ for (const p of options.getProperties())
197
+ addSetting(mapCall, p.getText());
198
+ options.replaceWithText("");
199
+ call.replaceWithText(call.getText().replace(/\.end\(\s*\)$/, ".end()"));
200
+ return "changed";
201
+ }
202
+ }
203
+ return undefined;
204
+ }
205
+ /** Rewrites the old flow forms in a project's source files; returns problems it left for a person. */
206
+ export function convertFlows(project, kindOf) {
207
+ const changed = new Set();
208
+ const problems = [];
209
+ const needsMap = new Set();
210
+ for (const sf of project.getSourceFiles()) {
211
+ // One rewrite per pass, innermost calls first, so a wrapper sees the map() chain its argument became. Calls left
212
+ // for a person never change, so the final pass (nothing left to rewrite) lists each of them once.
213
+ const rewritten = new Set();
214
+ for (;;) {
215
+ let progressed = false;
216
+ const left = [];
217
+ for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression).reverse()) {
218
+ if (call.wasForgotten())
219
+ continue;
220
+ const top = sf.getStatements().indexOf(call.getFirstAncestor((a) => a.getParent() === sf));
221
+ const result = rewrite(call, kindOf, needsMap);
222
+ if (result === "changed") {
223
+ changed.add(sf);
224
+ rewritten.add(top);
225
+ progressed = true;
226
+ break;
227
+ }
228
+ if (result)
229
+ left.push({ file: sf.getFilePath(), line: call.getStartLineNumber(), reason: result });
230
+ }
231
+ if (!progressed) {
232
+ problems.push(...left.reverse());
233
+ break;
234
+ }
235
+ }
236
+ if (!changed.has(sf))
237
+ continue;
238
+ // Replacing nested calls leaves odd indentation behind; TypeScript's formatter tidies just the rewritten statements.
239
+ const statements = sf.getStatements();
240
+ for (const i of rewritten)
241
+ statements[i]?.formatText({ indentSize: 2, convertTabsToSpaces: true });
242
+ for (const imp of sf.getImportDeclarations()) {
243
+ if (imp.getModuleSpecifierValue() !== "waygraph")
244
+ continue;
245
+ for (const n of imp.getNamedImports()) {
246
+ const local = n.getAliasNode()?.getText() ?? n.getName();
247
+ const stillUsed = sf.getDescendantsOfKind(SyntaxKind.Identifier).some((i) => {
248
+ const parent = i.getParent();
249
+ if (i.getText() !== local || Node.isImportSpecifier(parent))
250
+ return false;
251
+ return !(Node.isPropertyAccessExpression(parent) && parent.getNameNode() === i);
252
+ });
253
+ if (REMOVED.has(n.getName()) && !stillUsed)
254
+ n.remove();
255
+ }
256
+ if (needsMap.has(sf) && !imp.getNamedImports().some((n) => n.getName() === "map"))
257
+ imp.addNamedImport("map");
258
+ if (imp.getNamedImports().length === 0 && !imp.getDefaultImport() && !imp.getNamespaceImport())
259
+ imp.remove();
260
+ }
261
+ }
262
+ return { changed: [...changed], problems };
263
+ }
264
+ /** Runs the codemod over a project's TypeScript files, using its runtime scan for each Block's kind. */
265
+ export async function codemodFlows(projectDir) {
266
+ const scan = await scanProject(projectDir, { flows: false, maps: false });
267
+ const kinds = new Map(scan.blocks.map((b) => [`${b.absFile}#${b.exportName}`, b.kind]));
268
+ // Compiler options from the project's tsconfig; files from walkDir, which skips node_modules, dist and .git.
269
+ const tsconfig = join(projectDir, "tsconfig.json");
270
+ const project = new Project({ ...(existsSync(tsconfig) ? { tsConfigFilePath: tsconfig } : {}), skipAddingFilesFromTsConfig: true });
271
+ for (const file of walkDir(projectDir, /\.ts$/))
272
+ if (!file.endsWith(".d.ts"))
273
+ project.addSourceFileAtPath(file);
274
+ const flows = convertFlows(project, (file, name) => kinds.get(`${file}#${name}`));
275
+ const stubs = convertStubs(project);
276
+ const changed = [...new Set([...flows.changed, ...stubs.changed])];
277
+ const problems = [...flows.problems, ...stubs.problems];
278
+ for (const sf of changed)
279
+ sf.saveSync();
280
+ return {
281
+ changed: changed.map((sf) => relative(projectDir, sf.getFilePath())),
282
+ problems: problems.map((p) => `${relative(projectDir, p.file)}:${p.line}: ${p.reason}`),
283
+ };
284
+ }
@@ -0,0 +1,10 @@
1
+ import type { Project, SourceFile } from "ts-morph";
2
+ /** Rewrites the old stub forms in every file; returns the files it changed and the calls left for a person. */
3
+ export declare function convertStubs(project: Project): {
4
+ changed: SourceFile[];
5
+ problems: {
6
+ file: string;
7
+ line: number;
8
+ reason: string;
9
+ }[];
10
+ };