waygraph 0.15.50 → 0.15.51

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 (462) hide show
  1. package/dist/analysis/map-check.js +5 -2
  2. package/dist/analysis/practices-check.js +17 -4
  3. package/dist/auto-session/session.js +2 -1
  4. package/dist/browser-path.d.ts +5 -0
  5. package/dist/browser-path.js +18 -0
  6. package/dist/cli/run-chain.js +1 -0
  7. package/dist/commands/init.js +5 -0
  8. package/dist/core/blocks/effect.d.ts +0 -3
  9. package/dist/core/blocks/method.d.ts +0 -6
  10. package/dist/core/blocks/nav.d.ts +0 -3
  11. package/dist/core/blocks/page.d.ts +0 -3
  12. package/dist/core/flow.js +3 -6
  13. package/dist/highlights/types.d.ts +3 -2
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +2 -0
  16. package/dist/runner/inpage/banner.js +10 -2
  17. package/dist/runner/main.js +10 -6
  18. package/dist/session/auto-explore-run.js +13 -2
  19. package/dist/traverse/run.js +2 -1
  20. package/dist/types.d.ts +0 -3
  21. package/dist/webserver.d.ts +14 -0
  22. package/dist/webserver.js +91 -0
  23. package/examples/routed-demo/package.json +3 -3
  24. package/examples/routed-demo/playwright.config.ts +8 -8
  25. package/examples/routed-demo/scripts/fixture-server.mjs +12 -31
  26. package/examples/routed-demo/src/map/(app_base)/dashboard/_sel.ts +1 -3
  27. package/examples/routed-demo/src/map/(external)/docs/_sel.ts +1 -3
  28. package/examples/routed-demo/src/pages/dashboard.html +1 -1
  29. package/examples/routed-demo/src/pages/docs.html +1 -1
  30. package/examples/saucedemo/playwright.config.ts +2 -3
  31. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +2 -1
  32. package/examples/saucedemo/scripts/prove-auto-graph.mjs +2 -1
  33. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +2 -1
  34. package/examples/saucedemo/tests/flow-block-verify.spec.ts +2 -7
  35. package/package.json +10 -2
  36. package/templates/quickstart/playwright.config.ts +0 -6
  37. package/templates/scaffold/README.md +5 -3
  38. package/templates/scaffold/STRUCTURE.md +3 -4
  39. package/templates/scaffold/package.json +8 -12
  40. package/templates/scaffold/playwright.config.ts +2 -18
  41. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +1 -1
  42. package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +2 -3
  43. package/templates/scaffold/src/map/(app_base)/docs/{docs.html → index.html} +1 -1
  44. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +12 -13
  45. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +19 -22
  46. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +7 -8
  47. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -8
  48. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +10 -10
  49. package/templates/scaffold/src/map/(app_base)/home/_sel.ts +2 -4
  50. package/templates/scaffold/src/map/(app_base)/index.html +17 -0
  51. package/templates/scaffold/src/states/demo.states.ts +2 -0
  52. package/templates/scaffold/tests/README.md +3 -2
  53. package/templates/scaffold/tsconfig.json +1 -1
  54. package/templates/skills/waygraph-convention.skill.md +5 -3
  55. package/templates/skills/waygraph-pilot.skill.md +1 -1
  56. package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
  57. package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
  58. package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
  59. package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
  60. package/examples/routed-demo/scripts/with-fixture.mjs +0 -70
  61. package/examples/saucedemo/.waygraph-auto/00b0c55c.log +0 -22
  62. package/examples/saucedemo/.waygraph-auto/00d147d1.log +0 -21
  63. package/examples/saucedemo/.waygraph-auto/00e5d037.log +0 -5
  64. package/examples/saucedemo/.waygraph-auto/015be8f6.log +0 -6
  65. package/examples/saucedemo/.waygraph-auto/026e188e.log +0 -0
  66. package/examples/saucedemo/.waygraph-auto/02f7dd22.log +0 -20
  67. package/examples/saucedemo/.waygraph-auto/03df352d.log +0 -0
  68. package/examples/saucedemo/.waygraph-auto/0402cfcf.log +0 -6
  69. package/examples/saucedemo/.waygraph-auto/050e5b55.log +0 -0
  70. package/examples/saucedemo/.waygraph-auto/05d76fc3.log +0 -0
  71. package/examples/saucedemo/.waygraph-auto/062b581f.log +0 -20
  72. package/examples/saucedemo/.waygraph-auto/0681582b.log +0 -6
  73. package/examples/saucedemo/.waygraph-auto/07845ed1.log +0 -0
  74. package/examples/saucedemo/.waygraph-auto/07f3e964.log +0 -6
  75. package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
  76. package/examples/saucedemo/.waygraph-auto/0924ddaa.log +0 -22
  77. package/examples/saucedemo/.waygraph-auto/092d6173.log +0 -5
  78. package/examples/saucedemo/.waygraph-auto/096fea05.log +0 -20
  79. package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
  80. package/examples/saucedemo/.waygraph-auto/0998c941.log +0 -21
  81. package/examples/saucedemo/.waygraph-auto/0a8c3719.log +0 -0
  82. package/examples/saucedemo/.waygraph-auto/0bf74300.log +0 -21
  83. package/examples/saucedemo/.waygraph-auto/0c01fd29.log +0 -4
  84. package/examples/saucedemo/.waygraph-auto/0c19e232.log +0 -5
  85. package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
  86. package/examples/saucedemo/.waygraph-auto/0dee62d6.log +0 -5
  87. package/examples/saucedemo/.waygraph-auto/0eb4c081.log +0 -5
  88. package/examples/saucedemo/.waygraph-auto/0f0cb120.log +0 -0
  89. package/examples/saucedemo/.waygraph-auto/102c38ca.log +0 -0
  90. package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
  91. package/examples/saucedemo/.waygraph-auto/1122c13c.log +0 -0
  92. package/examples/saucedemo/.waygraph-auto/123d1cad.log +0 -5
  93. package/examples/saucedemo/.waygraph-auto/12ed8e28.log +0 -0
  94. package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
  95. package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
  96. package/examples/saucedemo/.waygraph-auto/161cc8dd.log +0 -22
  97. package/examples/saucedemo/.waygraph-auto/164761a5.log +0 -6
  98. package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
  99. package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
  100. package/examples/saucedemo/.waygraph-auto/1b80fd24.log +0 -6
  101. package/examples/saucedemo/.waygraph-auto/1bd7b7bf.log +0 -0
  102. package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
  103. package/examples/saucedemo/.waygraph-auto/1c58a174.log +0 -0
  104. package/examples/saucedemo/.waygraph-auto/1cb6f44c.log +0 -5
  105. package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
  106. package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
  107. package/examples/saucedemo/.waygraph-auto/1f233a4c.log +0 -6
  108. package/examples/saucedemo/.waygraph-auto/1fdb2100.log +0 -0
  109. package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
  110. package/examples/saucedemo/.waygraph-auto/20e91af6.log +0 -5
  111. package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
  112. package/examples/saucedemo/.waygraph-auto/22048fff.log +0 -4
  113. package/examples/saucedemo/.waygraph-auto/222d1d09.log +0 -0
  114. package/examples/saucedemo/.waygraph-auto/22f1a704.log +0 -5
  115. package/examples/saucedemo/.waygraph-auto/2324269a.log +0 -0
  116. package/examples/saucedemo/.waygraph-auto/232a1d81.log +0 -0
  117. package/examples/saucedemo/.waygraph-auto/239cced3.log +0 -20
  118. package/examples/saucedemo/.waygraph-auto/25204b46.log +0 -4
  119. package/examples/saucedemo/.waygraph-auto/2553d107.log +0 -0
  120. package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
  121. package/examples/saucedemo/.waygraph-auto/2708455e.log +0 -22
  122. package/examples/saucedemo/.waygraph-auto/272a96fd.log +0 -20
  123. package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
  124. package/examples/saucedemo/.waygraph-auto/2a577961.log +0 -0
  125. package/examples/saucedemo/.waygraph-auto/2a6a8266.log +0 -6
  126. package/examples/saucedemo/.waygraph-auto/2b3401cf.log +0 -20
  127. package/examples/saucedemo/.waygraph-auto/2b831907.log +0 -6
  128. package/examples/saucedemo/.waygraph-auto/2b9b56fc.log +0 -20
  129. package/examples/saucedemo/.waygraph-auto/2c79c73a.log +0 -0
  130. package/examples/saucedemo/.waygraph-auto/2c94a05b.log +0 -0
  131. package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
  132. package/examples/saucedemo/.waygraph-auto/2e2069e7.log +0 -0
  133. package/examples/saucedemo/.waygraph-auto/2e6bc35e.log +0 -6
  134. package/examples/saucedemo/.waygraph-auto/2efd1983.log +0 -0
  135. package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +0 -6
  136. package/examples/saucedemo/.waygraph-auto/2f4f531e.log +0 -0
  137. package/examples/saucedemo/.waygraph-auto/2f8d4073.log +0 -6
  138. package/examples/saucedemo/.waygraph-auto/2fdbd916.log +0 -0
  139. package/examples/saucedemo/.waygraph-auto/30739278.log +0 -6
  140. package/examples/saucedemo/.waygraph-auto/30a5c848.log +0 -20
  141. package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
  142. package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
  143. package/examples/saucedemo/.waygraph-auto/3239aa8a.log +0 -6
  144. package/examples/saucedemo/.waygraph-auto/326d87b7.log +0 -6
  145. package/examples/saucedemo/.waygraph-auto/331c6e8e.log +0 -0
  146. package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
  147. package/examples/saucedemo/.waygraph-auto/33a50dc0.log +0 -0
  148. package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
  149. package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
  150. package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
  151. package/examples/saucedemo/.waygraph-auto/372536a5.log +0 -6
  152. package/examples/saucedemo/.waygraph-auto/37b56184.log +0 -0
  153. package/examples/saucedemo/.waygraph-auto/38f6799d.log +0 -0
  154. package/examples/saucedemo/.waygraph-auto/3a208bb8.log +0 -20
  155. package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
  156. package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
  157. package/examples/saucedemo/.waygraph-auto/3a8674d5.log +0 -6
  158. package/examples/saucedemo/.waygraph-auto/3bdb2f5a.log +0 -0
  159. package/examples/saucedemo/.waygraph-auto/3c1e5fe0.log +0 -22
  160. package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
  161. package/examples/saucedemo/.waygraph-auto/3e3c0f3b.log +0 -0
  162. package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
  163. package/examples/saucedemo/.waygraph-auto/3f088138.log +0 -0
  164. package/examples/saucedemo/.waygraph-auto/401177a3.log +0 -0
  165. package/examples/saucedemo/.waygraph-auto/413d934d.log +0 -0
  166. package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
  167. package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
  168. package/examples/saucedemo/.waygraph-auto/41d0793d.log +0 -4
  169. package/examples/saucedemo/.waygraph-auto/41e6feae.log +0 -0
  170. package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
  171. package/examples/saucedemo/.waygraph-auto/42e014d1.log +0 -0
  172. package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
  173. package/examples/saucedemo/.waygraph-auto/432d09e3.log +0 -22
  174. package/examples/saucedemo/.waygraph-auto/438c6c53.log +0 -22
  175. package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
  176. package/examples/saucedemo/.waygraph-auto/47247959.log +0 -0
  177. package/examples/saucedemo/.waygraph-auto/476cff76.log +0 -0
  178. package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
  179. package/examples/saucedemo/.waygraph-auto/4ad09ece.log +0 -0
  180. package/examples/saucedemo/.waygraph-auto/4adcd179.log +0 -20
  181. package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +0 -21
  182. package/examples/saucedemo/.waygraph-auto/4cebc228.log +0 -20
  183. package/examples/saucedemo/.waygraph-auto/4da39c36.log +0 -6
  184. package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +0 -5
  185. package/examples/saucedemo/.waygraph-auto/4efa7035.log +0 -6
  186. package/examples/saucedemo/.waygraph-auto/505affdc.log +0 -4
  187. package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
  188. package/examples/saucedemo/.waygraph-auto/527b6d76.log +0 -0
  189. package/examples/saucedemo/.waygraph-auto/5291bc78.log +0 -22
  190. package/examples/saucedemo/.waygraph-auto/535e8922.log +0 -0
  191. package/examples/saucedemo/.waygraph-auto/54274c39.log +0 -5
  192. package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
  193. package/examples/saucedemo/.waygraph-auto/5738175f.log +0 -22
  194. package/examples/saucedemo/.waygraph-auto/573abedd.log +0 -0
  195. package/examples/saucedemo/.waygraph-auto/57ce5643.log +0 -22
  196. package/examples/saucedemo/.waygraph-auto/5984426b.log +0 -6
  197. package/examples/saucedemo/.waygraph-auto/5a682e7c.log +0 -22
  198. package/examples/saucedemo/.waygraph-auto/5b79320c.log +0 -21
  199. package/examples/saucedemo/.waygraph-auto/5b838485.log +0 -0
  200. package/examples/saucedemo/.waygraph-auto/5c55aaac.log +0 -21
  201. package/examples/saucedemo/.waygraph-auto/5d13bdde.log +0 -0
  202. package/examples/saucedemo/.waygraph-auto/5d285cd3.log +0 -0
  203. package/examples/saucedemo/.waygraph-auto/5ed00b16.log +0 -4
  204. package/examples/saucedemo/.waygraph-auto/60b9c066.log +0 -6
  205. package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
  206. package/examples/saucedemo/.waygraph-auto/61105500.log +0 -5
  207. package/examples/saucedemo/.waygraph-auto/61333142.log +0 -5
  208. package/examples/saucedemo/.waygraph-auto/6134afe8.log +0 -20
  209. package/examples/saucedemo/.waygraph-auto/61937e83.log +0 -22
  210. package/examples/saucedemo/.waygraph-auto/625e7f65.log +0 -5
  211. package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +0 -22
  212. package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
  213. package/examples/saucedemo/.waygraph-auto/63b0f4cd.log +0 -0
  214. package/examples/saucedemo/.waygraph-auto/6599cbca.log +0 -22
  215. package/examples/saucedemo/.waygraph-auto/6706ead4.log +0 -0
  216. package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
  217. package/examples/saucedemo/.waygraph-auto/685714af.log +0 -0
  218. package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
  219. package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
  220. package/examples/saucedemo/.waygraph-auto/68df05a6.log +0 -22
  221. package/examples/saucedemo/.waygraph-auto/68fa0682.log +0 -0
  222. package/examples/saucedemo/.waygraph-auto/693f67c4.log +0 -20
  223. package/examples/saucedemo/.waygraph-auto/69ae030a.log +0 -6
  224. package/examples/saucedemo/.waygraph-auto/69e73f35.log +0 -6
  225. package/examples/saucedemo/.waygraph-auto/6b2333b0.log +0 -5
  226. package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
  227. package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
  228. package/examples/saucedemo/.waygraph-auto/6d65a439.log +0 -5
  229. package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
  230. package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
  231. package/examples/saucedemo/.waygraph-auto/6f05bdc1.log +0 -0
  232. package/examples/saucedemo/.waygraph-auto/70279fc3.log +0 -0
  233. package/examples/saucedemo/.waygraph-auto/70c97639.log +0 -0
  234. package/examples/saucedemo/.waygraph-auto/72675b2d.log +0 -6
  235. package/examples/saucedemo/.waygraph-auto/731a14bd.log +0 -0
  236. package/examples/saucedemo/.waygraph-auto/733dd260.log +0 -5
  237. package/examples/saucedemo/.waygraph-auto/73a41843.log +0 -0
  238. package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
  239. package/examples/saucedemo/.waygraph-auto/752b01c6.log +0 -22
  240. package/examples/saucedemo/.waygraph-auto/75675227.log +0 -6
  241. package/examples/saucedemo/.waygraph-auto/756fd326.log +0 -20
  242. package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
  243. package/examples/saucedemo/.waygraph-auto/76128a2d.log +0 -0
  244. package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
  245. package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
  246. package/examples/saucedemo/.waygraph-auto/7773a809.log +0 -0
  247. package/examples/saucedemo/.waygraph-auto/78043767.log +0 -20
  248. package/examples/saucedemo/.waygraph-auto/792671f4.log +0 -22
  249. package/examples/saucedemo/.waygraph-auto/796ab578.log +0 -0
  250. package/examples/saucedemo/.waygraph-auto/79915adb.log +0 -20
  251. package/examples/saucedemo/.waygraph-auto/7a398774.log +0 -6
  252. package/examples/saucedemo/.waygraph-auto/7a72f66e.log +0 -6
  253. package/examples/saucedemo/.waygraph-auto/7a984334.log +0 -4
  254. package/examples/saucedemo/.waygraph-auto/7b226350.log +0 -5
  255. package/examples/saucedemo/.waygraph-auto/7c6ee793.log +0 -20
  256. package/examples/saucedemo/.waygraph-auto/7c726dc4.log +0 -22
  257. package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +0 -4
  258. package/examples/saucedemo/.waygraph-auto/7c99674f.log +0 -0
  259. package/examples/saucedemo/.waygraph-auto/7dbee625.log +0 -22
  260. package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
  261. package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
  262. package/examples/saucedemo/.waygraph-auto/7e8a6b62.log +0 -0
  263. package/examples/saucedemo/.waygraph-auto/7effd5b2.log +0 -20
  264. package/examples/saucedemo/.waygraph-auto/7f1b4864.log +0 -0
  265. package/examples/saucedemo/.waygraph-auto/7f94fd02.log +0 -0
  266. package/examples/saucedemo/.waygraph-auto/7fcb512f.log +0 -22
  267. package/examples/saucedemo/.waygraph-auto/7fdd47ee.log +0 -2
  268. package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
  269. package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
  270. package/examples/saucedemo/.waygraph-auto/80a4978e.log +0 -6
  271. package/examples/saucedemo/.waygraph-auto/81257bf0.log +0 -0
  272. package/examples/saucedemo/.waygraph-auto/81cfe480.log +0 -22
  273. package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
  274. package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
  275. package/examples/saucedemo/.waygraph-auto/8481aa1c.log +0 -0
  276. package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
  277. package/examples/saucedemo/.waygraph-auto/849ed45d.log +0 -0
  278. package/examples/saucedemo/.waygraph-auto/84dc6480.log +0 -6
  279. package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
  280. package/examples/saucedemo/.waygraph-auto/8598b4c0.log +0 -0
  281. package/examples/saucedemo/.waygraph-auto/859a261d.log +0 -0
  282. package/examples/saucedemo/.waygraph-auto/86350ea6.log +0 -22
  283. package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
  284. package/examples/saucedemo/.waygraph-auto/86d09876.log +0 -22
  285. package/examples/saucedemo/.waygraph-auto/878ad01b.log +0 -4
  286. package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
  287. package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
  288. package/examples/saucedemo/.waygraph-auto/880b2e78.log +0 -6
  289. package/examples/saucedemo/.waygraph-auto/88527936.log +0 -5
  290. package/examples/saucedemo/.waygraph-auto/88eda676.log +0 -0
  291. package/examples/saucedemo/.waygraph-auto/893023ea.log +0 -5
  292. package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
  293. package/examples/saucedemo/.waygraph-auto/8996a857.log +0 -6
  294. package/examples/saucedemo/.waygraph-auto/8a08b68d.log +0 -6
  295. package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +0 -6
  296. package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +0 -6
  297. package/examples/saucedemo/.waygraph-auto/8b73d13e.log +0 -6
  298. package/examples/saucedemo/.waygraph-auto/8be93021.log +0 -0
  299. package/examples/saucedemo/.waygraph-auto/8d960d31.log +0 -1
  300. package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +0 -21
  301. package/examples/saucedemo/.waygraph-auto/8e12e34f.log +0 -22
  302. package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
  303. package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
  304. package/examples/saucedemo/.waygraph-auto/93acae32.log +0 -5
  305. package/examples/saucedemo/.waygraph-auto/94221b2b.log +0 -0
  306. package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
  307. package/examples/saucedemo/.waygraph-auto/9742b6c2.log +0 -6
  308. package/examples/saucedemo/.waygraph-auto/9761c4c4.log +0 -6
  309. package/examples/saucedemo/.waygraph-auto/976394cd.log +0 -20
  310. package/examples/saucedemo/.waygraph-auto/982138cf.log +0 -0
  311. package/examples/saucedemo/.waygraph-auto/99cc93eb.log +0 -6
  312. package/examples/saucedemo/.waygraph-auto/9a26134c.log +0 -20
  313. package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
  314. package/examples/saucedemo/.waygraph-auto/9d827954.log +0 -20
  315. package/examples/saucedemo/.waygraph-auto/9dc147d2.log +0 -22
  316. package/examples/saucedemo/.waygraph-auto/9dd78c5e.log +0 -0
  317. package/examples/saucedemo/.waygraph-auto/a1ab5d29.log +0 -0
  318. package/examples/saucedemo/.waygraph-auto/a215a395.log +0 -22
  319. package/examples/saucedemo/.waygraph-auto/a23b7086.log +0 -4
  320. package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
  321. package/examples/saucedemo/.waygraph-auto/a4b36275.log +0 -0
  322. package/examples/saucedemo/.waygraph-auto/a4f8d355.log +0 -20
  323. package/examples/saucedemo/.waygraph-auto/a68995e9.log +0 -22
  324. package/examples/saucedemo/.waygraph-auto/a6e4f936.log +0 -22
  325. package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
  326. package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
  327. package/examples/saucedemo/.waygraph-auto/a8645294.log +0 -0
  328. package/examples/saucedemo/.waygraph-auto/a94738b7.log +0 -0
  329. package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
  330. package/examples/saucedemo/.waygraph-auto/a9559653.log +0 -5
  331. package/examples/saucedemo/.waygraph-auto/aa1beafb.log +0 -0
  332. package/examples/saucedemo/.waygraph-auto/aa226dd0.log +0 -22
  333. package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
  334. package/examples/saucedemo/.waygraph-auto/aa7323f8.log +0 -20
  335. package/examples/saucedemo/.waygraph-auto/aaae4fb0.log +0 -20
  336. package/examples/saucedemo/.waygraph-auto/ac350fc7.log +0 -20
  337. package/examples/saucedemo/.waygraph-auto/ac5dde3d.log +0 -0
  338. package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
  339. package/examples/saucedemo/.waygraph-auto/ad0bfad9.log +0 -5
  340. package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
  341. package/examples/saucedemo/.waygraph-auto/ae3a9b06.log +0 -0
  342. package/examples/saucedemo/.waygraph-auto/af2fae12.log +0 -0
  343. package/examples/saucedemo/.waygraph-auto/b04638f4.log +0 -6
  344. package/examples/saucedemo/.waygraph-auto/b0752c49.log +0 -0
  345. package/examples/saucedemo/.waygraph-auto/b14811d7.log +0 -6
  346. package/examples/saucedemo/.waygraph-auto/b2d2dbb2.log +0 -22
  347. package/examples/saucedemo/.waygraph-auto/b3d172f3.log +0 -0
  348. package/examples/saucedemo/.waygraph-auto/b48863e5.log +0 -22
  349. package/examples/saucedemo/.waygraph-auto/b5569336.log +0 -0
  350. package/examples/saucedemo/.waygraph-auto/b56968e1.log +0 -6
  351. package/examples/saucedemo/.waygraph-auto/b57921c5.log +0 -0
  352. package/examples/saucedemo/.waygraph-auto/b64e0620.log +0 -20
  353. package/examples/saucedemo/.waygraph-auto/b75168f7.log +0 -1
  354. package/examples/saucedemo/.waygraph-auto/b86a6218.log +0 -6
  355. package/examples/saucedemo/.waygraph-auto/b8e9e956.log +0 -22
  356. package/examples/saucedemo/.waygraph-auto/b9ab0983.log +0 -0
  357. package/examples/saucedemo/.waygraph-auto/b9b310ff.log +0 -21
  358. package/examples/saucedemo/.waygraph-auto/bb0e0e46.log +0 -0
  359. package/examples/saucedemo/.waygraph-auto/bc111745.log +0 -22
  360. package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
  361. package/examples/saucedemo/.waygraph-auto/bf85a598.log +0 -0
  362. package/examples/saucedemo/.waygraph-auto/bf8693e7.log +0 -0
  363. package/examples/saucedemo/.waygraph-auto/c0d6f353.log +0 -21
  364. package/examples/saucedemo/.waygraph-auto/c0febcf2.log +0 -20
  365. package/examples/saucedemo/.waygraph-auto/c4c52998.log +0 -6
  366. package/examples/saucedemo/.waygraph-auto/c52bac6d.log +0 -0
  367. package/examples/saucedemo/.waygraph-auto/c60cc55e.log +0 -0
  368. package/examples/saucedemo/.waygraph-auto/c809ceb4.log +0 -22
  369. package/examples/saucedemo/.waygraph-auto/c851cc53.log +0 -6
  370. package/examples/saucedemo/.waygraph-auto/c8987b67.log +0 -0
  371. package/examples/saucedemo/.waygraph-auto/c9d76e32.log +0 -0
  372. package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
  373. package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
  374. package/examples/saucedemo/.waygraph-auto/cae91469.log +0 -0
  375. package/examples/saucedemo/.waygraph-auto/cb05d223.log +0 -0
  376. package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
  377. package/examples/saucedemo/.waygraph-auto/cb9a1978.log +0 -6
  378. package/examples/saucedemo/.waygraph-auto/cbbc689c.log +0 -6
  379. package/examples/saucedemo/.waygraph-auto/cc989184.log +0 -20
  380. package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
  381. package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
  382. package/examples/saucedemo/.waygraph-auto/ce584949.log +0 -5
  383. package/examples/saucedemo/.waygraph-auto/cf34b895.log +0 -2
  384. package/examples/saucedemo/.waygraph-auto/cfff9eef.log +0 -20
  385. package/examples/saucedemo/.waygraph-auto/d0f59b21.log +0 -4
  386. package/examples/saucedemo/.waygraph-auto/d1195079.log +0 -20
  387. package/examples/saucedemo/.waygraph-auto/d2ef067a.log +0 -5
  388. package/examples/saucedemo/.waygraph-auto/d37719a6.log +0 -0
  389. package/examples/saucedemo/.waygraph-auto/d425471f.log +0 -6
  390. package/examples/saucedemo/.waygraph-auto/d4afe93f.log +0 -5
  391. package/examples/saucedemo/.waygraph-auto/d50e58f0.log +0 -0
  392. package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
  393. package/examples/saucedemo/.waygraph-auto/d62a22c2.log +0 -21
  394. package/examples/saucedemo/.waygraph-auto/d6d1761f.log +0 -22
  395. package/examples/saucedemo/.waygraph-auto/d6d5f411.log +0 -22
  396. package/examples/saucedemo/.waygraph-auto/d6df2771.log +0 -6
  397. package/examples/saucedemo/.waygraph-auto/d7075012.log +0 -21
  398. package/examples/saucedemo/.waygraph-auto/d846cd78.log +0 -0
  399. package/examples/saucedemo/.waygraph-auto/d934da78.log +0 -0
  400. package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
  401. package/examples/saucedemo/.waygraph-auto/da0a06bf.log +0 -0
  402. package/examples/saucedemo/.waygraph-auto/da6ebb31.log +0 -0
  403. package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
  404. package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
  405. package/examples/saucedemo/.waygraph-auto/db81ba7d.log +0 -0
  406. package/examples/saucedemo/.waygraph-auto/db839827.log +0 -5
  407. package/examples/saucedemo/.waygraph-auto/dc58eb72.log +0 -0
  408. package/examples/saucedemo/.waygraph-auto/dddd057c.log +0 -20
  409. package/examples/saucedemo/.waygraph-auto/dde5e859.log +0 -22
  410. package/examples/saucedemo/.waygraph-auto/ddf975e6.log +0 -0
  411. package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
  412. package/examples/saucedemo/.waygraph-auto/de8cb83d.log +0 -6
  413. package/examples/saucedemo/.waygraph-auto/ded5511a.log +0 -6
  414. package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
  415. package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
  416. package/examples/saucedemo/.waygraph-auto/e03cfd8e.log +0 -0
  417. package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
  418. package/examples/saucedemo/.waygraph-auto/e1b0676d.log +0 -21
  419. package/examples/saucedemo/.waygraph-auto/e230f24e.log +0 -0
  420. package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
  421. package/examples/saucedemo/.waygraph-auto/e5127c03.log +0 -22
  422. package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +0 -5
  423. package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
  424. package/examples/saucedemo/.waygraph-auto/eb38d92e.log +0 -22
  425. package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
  426. package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
  427. package/examples/saucedemo/.waygraph-auto/edd40cbb.log +0 -20
  428. package/examples/saucedemo/.waygraph-auto/eddfbffc.log +0 -6
  429. package/examples/saucedemo/.waygraph-auto/ee86203e.log +0 -0
  430. package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +0 -5
  431. package/examples/saucedemo/.waygraph-auto/ef319474.log +0 -22
  432. package/examples/saucedemo/.waygraph-auto/f1f38eeb.log +0 -22
  433. package/examples/saucedemo/.waygraph-auto/f24b2915.log +0 -0
  434. package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
  435. package/examples/saucedemo/.waygraph-auto/f2943898.log +0 -0
  436. package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
  437. package/examples/saucedemo/.waygraph-auto/f43de83c.log +0 -0
  438. package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +0 -6
  439. package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +0 -20
  440. package/examples/saucedemo/.waygraph-auto/f86224c6.log +0 -0
  441. package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
  442. package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +0 -22
  443. package/examples/saucedemo/.waygraph-auto/f92faf40.log +0 -5
  444. package/examples/saucedemo/.waygraph-auto/fa784369.log +0 -21
  445. package/examples/saucedemo/.waygraph-auto/fb55f723.log +0 -20
  446. package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
  447. package/examples/saucedemo/.waygraph-auto/fc917c18.log +0 -0
  448. package/examples/saucedemo/.waygraph-auto/fdf66b74.log +0 -0
  449. package/examples/saucedemo/.waygraph-auto/fe83305d.log +0 -0
  450. package/examples/saucedemo/.waygraph-auto/ff616932.log +0 -0
  451. package/examples/saucedemo/.waygraph-auto/ffdf2854.log +0 -6
  452. package/examples/saucedemo/scripts/capture-auto-headful.mjs +0 -120
  453. package/examples/saucedemo/scripts/capture-wrong-login.mjs +0 -141
  454. package/examples/saucedemo/scripts/demo-device-presets.mjs +0 -188
  455. package/examples/saucedemo/scripts/demo-orientation-gestures-video.mjs +0 -262
  456. package/examples/saucedemo/scripts/show-add-to-cart-menu.mjs +0 -123
  457. package/examples/saucedemo/scripts/show-auto-menu.mjs +0 -72
  458. package/templates/scaffold/scripts/README.md +0 -13
  459. package/templates/scaffold/scripts/fixture-server.mjs +0 -50
  460. package/templates/scaffold/scripts/with-fixture.mjs +0 -69
  461. package/templates/scaffold/test-results/.last-run.json +0 -4
  462. /package/templates/scaffold/src/map/(app_base)/home/{home.html → index.html} +0 -0
@@ -117,12 +117,15 @@ export async function checkMap(projectDir) {
117
117
  continue; // only statically-urled Nav/Page Blocks are checkable
118
118
  let pathname;
119
119
  try {
120
- pathname = new URL(navUrl).pathname;
120
+ // Relative URLs (the normal baseUrl case) are paths from the app root.
121
+ pathname = new URL(navUrl, "http://app.invalid/").pathname;
121
122
  }
122
123
  catch {
123
- continue; // a relative/templated URL - not verbatim-checkable
124
+ continue;
124
125
  }
125
126
  const urlSegments = pathname.split("/").filter(Boolean);
127
+ if (urlSegments.at(-1) === "index.html")
128
+ urlSegments.pop(); // /docs/index.html is the docs/ folder
126
129
  const folderSegments = realSegments(relative(mapRoot, file));
127
130
  const matches = urlSegments.length === folderSegments.length && urlSegments.every((s, i) => s === folderSegments[i]);
128
131
  if (!matches) {
@@ -5,8 +5,20 @@
5
5
  */
6
6
  import { readFileSync, readdirSync } from "node:fs";
7
7
  import { dirname, relative } from "node:path";
8
- /** define*Block<…Checkpoint<string>…> — prefer project Checkpoint types. */
9
- const WILDCARD_CHECKPOINT = /\bdefine(?:Method|Effect|Page|Nav|MemNav|NavClick|Action)Block\s*<[^>]*\bCheckpoint\s*<\s*string\s*>/;
8
+ /** Every define*Block<In, Out> / <Out> generic list - args may themselves be Checkpoint<...>. */
9
+ const BLOCK_GENERICS = /\bdefine(?:Method|Effect|MemEffect|Page|Nav|MemNav|NavClick|Action)Block\s*<\s*((?:Checkpoint\s*<[^>]*>|[^,<>])+?)\s*(?:,\s*((?:Checkpoint\s*<[^>]*>|[^,<>])+?)\s*)?>/g;
10
+ /**
11
+ * A wildcard Out (the Block's result is untyped). A wildcard In is fine - it's the documented
12
+ * "reachable from anywhere" form (graph.ts treats it like a NavBlock's "*").
13
+ */
14
+ function hasWildcardOut(src) {
15
+ for (const m of src.matchAll(BLOCK_GENERICS)) {
16
+ const out = (m[2] ?? m[1]).trim();
17
+ if (/^Checkpoint\s*<\s*string\s*>$/.test(out))
18
+ return true;
19
+ }
20
+ return false;
21
+ }
10
22
  /** defineAssertBlock({ … }) with no explicit Out type — defaults to wildcard. */
11
23
  const ASSERT_NO_TYPE_ARG = /\bdefineAssertBlock\s*\(\s*\{/;
12
24
  /** defineAssertBlock, any form - used to scope the empty-verify check below. */
@@ -74,11 +86,12 @@ export function collectPracticeWarnings(projectDir, walkDir, opts) {
74
86
  const rel = relative(projectDir, file).replace(/\\/g, "/");
75
87
  const src = readFileSync(file, "utf-8");
76
88
  const ignore = ignoredKindsForFile(src);
77
- if (!isIgnored("wildcard-checkpoint", ignore) && WILDCARD_CHECKPOINT.test(src)) {
89
+ if (!isIgnored("wildcard-checkpoint", ignore) && hasWildcardOut(src)) {
78
90
  warnings.push({
79
91
  kind: "wildcard-checkpoint",
80
92
  file: rel,
81
- detail: 'uses Checkpoint<string> in a Block helper generic — prefer a typed Checkpoint from src/states/ (e.g. defineMethodBlock<LoginPage, LoginPage>)',
93
+ detail: "the Block's output is Checkpoint<string>, so its result is untyped — use a typed Checkpoint from " +
94
+ "src/states/ (e.g. defineMethodBlock<LoginPage, LoggedIn>); a wildcard input is fine",
82
95
  });
83
96
  }
84
97
  if (!isIgnored("assert-no-type-arg", ignore) && ASSERT_NO_TYPE_ARG.test(src)) {
@@ -9,6 +9,7 @@ import { collectKnownInteractionSelectors, unmappedInteractionsPageScript } from
9
9
  import { runStubPhase } from "../highlights.js";
10
10
  import { verboseLog } from "./verbose-log.js";
11
11
  import { findBlockPathDetailed } from "../analysis/graph.js";
12
+ import { chromiumExecutablePath } from "../browser-path.js";
12
13
  /**
13
14
  * Non-interactive explore session: same graph/library/mem/browser setup
14
15
  * `runAutoExplore` runs in `--cli` mode, driven by `applyPick` instead of a
@@ -67,7 +68,7 @@ export class AutoSession {
67
68
  const headless = init.headless ?? true;
68
69
  const engine = new Engine({ headless });
69
70
  const { chromium } = await import("@playwright/test");
70
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
71
+ const executablePath = chromiumExecutablePath();
71
72
  // Real gap found live: a headed (--non-headless) session kept a fixed
72
73
  // 1280x720 content area even when the user maximized/fullscreened the
73
74
  // actual window - `viewport: null` alone only makes the PAGE track the
@@ -0,0 +1,5 @@
1
+ /**
2
+ * CHROME_PATH / CHROMIUM_PATH, if set and the file exists. A stale path (browser uninstalled)
3
+ * falls back to Playwright's bundled Chromium with a one-time warning instead of failing the run.
4
+ */
5
+ export declare function chromiumExecutablePath(): string | undefined;
@@ -0,0 +1,18 @@
1
+ import { existsSync } from "node:fs";
2
+ let warned = false;
3
+ /**
4
+ * CHROME_PATH / CHROMIUM_PATH, if set and the file exists. A stale path (browser uninstalled)
5
+ * falls back to Playwright's bundled Chromium with a one-time warning instead of failing the run.
6
+ */
7
+ export function chromiumExecutablePath() {
8
+ const path = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
9
+ if (!path)
10
+ return undefined;
11
+ if (existsSync(path))
12
+ return path;
13
+ if (!warned) {
14
+ warned = true;
15
+ console.error(`waygraph: CHROME_PATH/CHROMIUM_PATH "${path}" does not exist - using Playwright's bundled Chromium`);
16
+ }
17
+ return undefined;
18
+ }
@@ -49,6 +49,7 @@ export async function runChain(projectDir, spec) {
49
49
  const scriptPath = join(projectDir, `.waygraph-chain-${process.pid}.mjs`);
50
50
  writeFileSync(scriptPath, CHAIN_RUNNER_BOOTSTRAP);
51
51
  try {
52
+ // webServer is started inside the child (runner/main.js), never here - see CHAIN_RUNNER_BOOTSTRAP.
52
53
  const code = await new Promise((res, rej) => {
53
54
  const child = spawn(process.execPath, ["--import", tsxEsm, scriptPath, projectDir, expanded], {
54
55
  stdio: "inherit",
@@ -2,6 +2,7 @@
2
2
  import { packageRoot } from "../cli/util.js";
3
3
  import { basename, join, relative, resolve } from "node:path";
4
4
  import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
5
+ import { pathToFileURL } from "node:url";
5
6
  function initCommand(projectName) {
6
7
  if (!projectName) {
7
8
  console.error("waygraph init: missing <project-name>, e.g. waygraph init my-app");
@@ -30,8 +31,12 @@ function initCommand(projectName) {
30
31
  writeFileSync(join(targetDir, ".gitignore"), readFileSync(gitignoreSrc, "utf-8"));
31
32
  rmSync(gitignoreSrc);
32
33
  }
34
+ // Demo pages open via file://; the absolute path is only known once copied, so it's filled in here.
35
+ const appBaseUrl = pathToFileURL(join(targetDir, "src", "map", "(app_base)", "index.html")).href;
33
36
  const packageJsonPath = join(targetDir, "package.json");
34
37
  writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__", pkgName));
38
+ const playwrightConfigPath = join(targetDir, "playwright.config.ts");
39
+ writeFileSync(playwrightConfigPath, readFileSync(playwrightConfigPath, "utf-8").replaceAll("__APP_BASE_URL__", appBaseUrl));
35
40
  console.log(`Scaffolded ${pkgName}/`);
36
41
  console.log("");
37
42
  console.log(` cd ${relative(process.cwd(), targetDir) || pkgName}`);
@@ -17,13 +17,10 @@ export type EffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<st
17
17
  modVerifyAll(patches: Record<string, Trait["check"] | Trait>): EffectBlock<In, Out>;
18
18
  stubBefore(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
19
19
  stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
20
- stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
21
20
  stubAfter(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
22
21
  stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
23
- stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
24
22
  stubOnError(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
25
23
  stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
26
- stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
27
24
  };
28
25
  /** @deprecated Prefer {@link EffectBlock} - same type; Mem* was an early name. */
29
26
  export type MemEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = EffectBlock<In, Out>;
@@ -17,13 +17,10 @@ export type MethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<st
17
17
  modVerifyAll(patches: Record<string, Trait["check"] | Trait>): MethodBlock<In, Out>;
18
18
  stubBefore(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
19
19
  stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
20
- stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
21
20
  stubAfter(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
22
21
  stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
23
- stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
24
22
  stubOnError(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
25
23
  stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
26
- stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
27
24
  };
28
25
  /** @deprecated Prefer {@link MethodBlock} - same type; Action was the 0.7 name. */
29
26
  export type ActionBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = MethodBlock<In, Out>;
@@ -80,11 +77,8 @@ export type AssertBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Out,
80
77
  modVerifyAll(patches: Record<string, Trait["check"] | Trait>): AssertBlock<Out>;
81
78
  stubBefore(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
82
79
  stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
83
- stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
84
80
  stubAfter(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
85
81
  stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
86
- stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
87
82
  stubOnError(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
88
83
  stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
89
- stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
90
84
  };
@@ -22,13 +22,10 @@ export type NavBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpo
22
22
  modVerifyAll(patches: Record<string, Trait["check"] | Trait>): NavBlock<Out>;
23
23
  stubBefore(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
24
24
  stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
25
- stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
26
25
  stubAfter(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
27
26
  stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
28
- stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
29
27
  stubOnError(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
30
28
  stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
31
- stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
32
29
  };
33
30
  /**
34
31
  * `defineNavBlock`'s own options - exactly one of `url`/`click` required,
@@ -47,13 +47,10 @@ export type PageBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkp
47
47
  modVerifyAll(patches: Record<string, Trait["check"] | Trait>): PageBlock<Out>;
48
48
  stubBefore(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
49
49
  stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
50
- stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
51
50
  stubAfter(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
52
51
  stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
53
- stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
54
52
  stubOnError(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
55
53
  stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
56
- stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
57
54
  };
58
55
  /** @see {@link PageBlockOptions} */
59
56
  export declare function definePageBlock<Out extends Checkpoint<string>>(options: PageBlockOptions<Out>): PageBlock<Out>;
package/dist/core/flow.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
2
2
  import { connect } from "../types.js";
3
+ import { chromiumExecutablePath } from "../browser-path.js";
3
4
  import { WaygraphError, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_INDEX, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_NAME, MSG_CHAINFLOW_EMPTY, } from "../errors.js";
4
5
  import { preflight, runGraph } from "./run-graph.js";
5
6
  import { resolveLauncher } from "./config.js";
@@ -33,11 +34,7 @@ export function buildFlow(middle, engineConfig) {
33
34
  preflight(mem, chain);
34
35
  const browserName = config.browserName ?? "chromium";
35
36
  const launch = resolveLauncher(browserName, config);
36
- // If CHROME_PATH/CHROMIUM_PATH is set in the environment (e.g. a system
37
- // or Flatpak Chromium), launch that instead of Playwright's own bundled
38
- // binary - only for chromium (the env var names a Chromium build, not a
39
- // Firefox/WebKit one), and a no-op default anywhere that env var isn't set.
40
- const executablePath = browserName === "chromium" ? process.env.CHROME_PATH || process.env.CHROMIUM_PATH : undefined;
37
+ const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
41
38
  const browser = await launch.launch({
42
39
  headless: config.headless ?? true,
43
40
  ...(config.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
@@ -324,7 +321,7 @@ export function chainFlow(...flows) {
324
321
  // session reset, silently making withSessionReset a no-op).
325
322
  const browserName = config?.browserName ?? "chromium";
326
323
  const launch = resolveLauncher(browserName, config);
327
- const executablePath = browserName === "chromium" ? process.env.CHROME_PATH || process.env.CHROMIUM_PATH : undefined;
324
+ const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
328
325
  const browser = await launch.launch({
329
326
  headless: config?.headless ?? true,
330
327
  ...(config?.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
@@ -464,9 +464,10 @@ export type StubLifecycleFn<Out extends Checkpoint<string>> = (ctx: StubCtx<Out>
464
464
  * Block stub authoring:
465
465
  * - **preferred:** open lifecycle `stubBefore(ctx) { ctx.todos(...); ctx.ring(...) }`
466
466
  * - **shorthand:** static slot map `{ email: { selector, label } }`
467
- * - **legacy:** `(out) => slotMap` still accepted (treated as highlights only)
467
+ *
468
+ * Exactly one function member, so an inline `stubAfter(ctx) {}` gets `ctx` typed.
468
469
  */
469
- export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | StubLifecycleFn<Out> | ((out: Out) => HighlightStubPhase);
470
+ export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | StubLifecycleFn<Out>;
470
471
  /** Result of running a stub phase (rings + episode fixtures). */
471
472
  export type StubPhaseResult = {
472
473
  highlights: ResolvedHighlight[];
package/dist/index.d.ts CHANGED
@@ -31,3 +31,6 @@ export { pilotStart } from "./session/pilot.js";
31
31
  export type { PilotStartResult } from "./session/pilot.js";
32
32
  export { defineConfig, resolveBaseUrl } from "./config.js";
33
33
  export type { WaygraphConfig } from "./config.js";
34
+ export { withWebServer } from "./webserver.js";
35
+ export { chromiumExecutablePath } from "./browser-path.js";
36
+ export type { WebServerConfig } from "./webserver.js";
package/dist/index.js CHANGED
@@ -15,3 +15,5 @@ export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL,
15
15
  export { AutoSession, stubFilePath } from "./auto-session.js";
16
16
  export { pilotStart } from "./session/pilot.js";
17
17
  export { defineConfig, resolveBaseUrl } from "./config.js";
18
+ export { withWebServer } from "./webserver.js";
19
+ export { chromiumExecutablePath } from "./browser-path.js";
@@ -101,28 +101,36 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
101
101
  );
102
102
  };
103
103
  const home = b.dataset.home || b.dataset.pos || "left";
104
+ // Called every animation frame while a ring is followed - only log when the outcome changes.
105
+ const log = (state, line) => {
106
+ if (b.dataset.lastLog === state) return;
107
+ b.dataset.lastLog = state;
108
+ if (line) (window.__wgBannerLog = window.__wgBannerLog || []).push(line);
109
+ };
104
110
  b.dataset.pos = home;
105
111
  if (!hits()) {
106
112
  delete b.dataset.moved;
113
+ log("clear");
107
114
  return;
108
115
  }
109
116
  for (const cand of POSITIONS.filter((p) => p !== home)) {
110
117
  b.dataset.pos = cand;
111
118
  if (!hits()) {
112
119
  b.dataset.moved = home + ">" + cand;
113
- (window.__wgBannerLog = window.__wgBannerLog || []).push("moved " + home + " -> " + cand + " (ring overlap)");
120
+ log("moved:" + cand, "moved " + home + " -> " + cand + " (ring overlap)");
114
121
  return;
115
122
  }
116
123
  }
117
124
  b.dataset.pos = home;
118
125
  b.dataset.moved = "none-free";
119
- (window.__wgBannerLog = window.__wgBannerLog || []).push("overlap at every position (kept " + home + ")");
126
+ log("none-free", "overlap at every position (kept " + home + ")");
120
127
  };
121
128
  window.__wgBannerRestore = () => {
122
129
  const b = __wgById("wg-banner");
123
130
  if (!b) return;
124
131
  if (b.dataset.home) b.dataset.pos = b.dataset.home;
125
132
  delete b.dataset.moved;
133
+ delete b.dataset.lastLog;
126
134
  };
127
135
  // Dim the banner while a ring caption is the focus - same "auto opacity" effect the todo
128
136
  // dock already has via __wgTodosSetBehind, extended to the banner so both floating chrome
@@ -9,8 +9,10 @@ import { runStepMode } from "./step-mode.js";
9
9
  import { connect } from "../types.js";
10
10
  import { MemPage } from "../mem-page.js";
11
11
  import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../core.js";
12
+ import { withWebServer } from "../webserver.js";
13
+ import { chromiumExecutablePath } from "../browser-path.js";
12
14
 
13
- async function main() {
15
+ async function runMain() {
14
16
  const projectDir = process.argv[2];
15
17
  const spec = process.argv[3];
16
18
  const mem = new MemPage();
@@ -285,11 +287,7 @@ async function main() {
285
287
  // launched at Chromium's own default size/position, which stayed put
286
288
  // where it was for a previous, larger monitor and looked chopped off on
287
289
  // a smaller one. Maximizing fills whatever screen it's actually on.
288
- // Same CHROME_PATH/CHROMIUM_PATH rule as Engine.run(mem): prefer the
289
- // system/Flatpak Chromium when set, otherwise Playwright's bundled build.
290
- // Without this, STEP mode always launched a different-looking browser than
291
- // headed Engine runs / waygraph-demo.mjs (which already resolve Flatpak).
292
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH || undefined;
290
+ const executablePath = chromiumExecutablePath();
293
291
  // Maximized for interactive step, and for fixed video viewport so the
294
292
  // locked record size can actually fit (otherwise .webm gets grey pad).
295
293
  const browser = await chromium.launch({
@@ -446,6 +444,12 @@ async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
446
444
  void engine;
447
445
  }
448
446
 
447
+ // Here, not in the host CLI: importing playwright.config loads the project's own @playwright/test,
448
+ // which would collide with the CLI's copy.
449
+ async function main() {
450
+ await withWebServer(process.argv[2], runMain);
451
+ }
452
+
449
453
  export function startRunner() {
450
454
  main().catch((err) => {
451
455
  console.error(err && err.stack ? err.stack : String(err));
@@ -6,6 +6,8 @@ import { MemPage } from "../mem-page.js";
6
6
  import { buildExploreContext, buildExploreMenu, } from "./auto-explore.js";
7
7
  import { installDemoChrome, instrumentInteractionHighlighting } from "./step-overlay.js";
8
8
  import { resolveBaseUrl } from "../config.js";
9
+ import { withWebServer } from "../webserver.js";
10
+ import { chromiumExecutablePath } from "../browser-path.js";
9
11
  /** See `../config.js`'s own `resolveBaseUrl` - re-exported so existing importers of this module
10
12
  * don't need to change their import path. */
11
13
  export { resolveBaseUrl };
@@ -540,7 +542,13 @@ function printCliMenu(menu, library) {
540
542
  }
541
543
  async function cliPick(menu, rl) {
542
544
  while (true) {
543
- const ans = (await rl.question("Choose: ")).trim().toLowerCase();
545
+ let ans;
546
+ try {
547
+ ans = (await rl.question("Choose: ")).trim().toLowerCase();
548
+ }
549
+ catch {
550
+ return { type: "quit" }; // stdin ended (piped / Ctrl-D) - same as q
551
+ }
544
552
  if (ans === "q" || ans === "quit")
545
553
  return { type: "quit" };
546
554
  const n = Number(ans);
@@ -554,6 +562,9 @@ async function cliPick(menu, rl) {
554
562
  * Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
555
563
  */
556
564
  export async function runAutoExplore(projectDir, options = {}) {
565
+ await withWebServer(projectDir, () => runAutoExploreCore(projectDir, options));
566
+ }
567
+ async function runAutoExploreCore(projectDir, options = {}) {
557
568
  lastRunNote = null;
558
569
  const cli = options.cli === true;
559
570
  const baseURL = options.baseURL ?? (await resolveBaseUrl(projectDir)) ?? process.env.WAYGRAPH_BASE_URL;
@@ -567,7 +578,7 @@ export async function runAutoExplore(projectDir, options = {}) {
567
578
  seedDefaultMem(library.byName, mem);
568
579
  const engine = cli ? new Engine({ headless: true }) : new Engine({ headless: false, slowMo: 250 });
569
580
  const { chromium } = await import("@playwright/test");
570
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
581
+ const executablePath = chromiumExecutablePath();
571
582
  const launchOpts = {
572
583
  headless: cli,
573
584
  args: cli ? [] : ["--start-maximized"],
@@ -5,6 +5,7 @@ import { defaultMemValueForKey } from "../session/auto-explore-run.js";
5
5
  import { resolveBaseUrl } from "../config.js";
6
6
  import { EdgeLeaseCoordinator } from "./lease.js";
7
7
  import { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, writeCoverageReport, } from "./coverage.js";
8
+ import { chromiumExecutablePath } from "../browser-path.js";
8
9
  function seedMem(library, mem, dataJson) {
9
10
  const raw = dataJson ?? process.env.WAYGRAPH_DATA ?? process.env.WAYGRAPH_AUTO_MEM;
10
11
  let envParsed = {};
@@ -253,7 +254,7 @@ export async function runTraverse(projectDir, options = {}) {
253
254
  const leases = new EdgeLeaseCoordinator({ projectDir, persist: parallel > 1 });
254
255
  const engine = new Engine({ headless: !headed, slowMo: headed ? 100 : 0 });
255
256
  const { chromium } = await import("@playwright/test");
256
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
257
+ const executablePath = chromiumExecutablePath();
257
258
  const launchOpts = {
258
259
  headless: !headed,
259
260
  };
package/dist/types.d.ts CHANGED
@@ -284,15 +284,12 @@ export type DefinedBlock<In extends Checkpoint<string>, Out extends Checkpoint<s
284
284
  */
285
285
  stubBefore(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
286
286
  stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
287
- stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
288
287
  /** Demo narration after resolve. Prefer ctx callbacks over slot-map objects. */
289
288
  stubAfter(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
290
289
  stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
291
- stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
292
290
  /** Demo narration when the step fails / expected-failure path. */
293
291
  stubOnError(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
294
292
  stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
295
- stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
296
293
  };
297
294
  /**
298
295
  * Structural (not imported) twin of `engine.ts`'s `Layout` - `types.ts` sits
@@ -0,0 +1,14 @@
1
+ /** The subset of Playwright's `TestConfigWebServer` this drives - same field names. */
2
+ export interface WebServerConfig {
3
+ command: string;
4
+ cwd?: string;
5
+ env?: Record<string, string>;
6
+ port?: number;
7
+ url?: string;
8
+ reuseExistingServer?: boolean;
9
+ timeout?: number;
10
+ stdout?: "pipe" | "ignore";
11
+ stderr?: "pipe" | "ignore";
12
+ }
13
+ /** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
14
+ export declare function withWebServer<T>(projectDir: string, fn: () => Promise<T>): Promise<T>;
@@ -0,0 +1,91 @@
1
+ // Starts/stops a project's own playwright.config `webServer` around `waygraph run`/`demo`/`auto`,
2
+ // the same block `waygraph test` already honors.
3
+ import { existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { spawn } from "node:child_process";
7
+ const CONFIG_FILES = [
8
+ "playwright.config.ts",
9
+ "playwright.config.mts",
10
+ "playwright.config.mjs",
11
+ "playwright.config.js",
12
+ "playwright.config.cjs",
13
+ ];
14
+ async function loadWebServerConfigs(projectDir) {
15
+ for (const name of CONFIG_FILES) {
16
+ const p = join(projectDir, name);
17
+ if (!existsSync(p))
18
+ continue;
19
+ let mod;
20
+ try {
21
+ mod = (await import(pathToFileURL(p).href));
22
+ }
23
+ catch (err) {
24
+ throw new Error(`waygraph: failed to load ${name}: ${err instanceof Error ? err.message : String(err)}`);
25
+ }
26
+ const webServer = mod.default?.webServer;
27
+ if (!webServer)
28
+ return [];
29
+ return Array.isArray(webServer) ? webServer : [webServer];
30
+ }
31
+ return [];
32
+ }
33
+ async function isUp(target) {
34
+ try {
35
+ return (await fetch(target)).status < 500;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ async function waitUntilUp(target, timeoutMs) {
42
+ const start = Date.now();
43
+ while (Date.now() - start < timeoutMs) {
44
+ if (await isUp(target))
45
+ return;
46
+ await new Promise((r) => setTimeout(r, 100));
47
+ }
48
+ throw new Error(`waygraph: webServer "${target}" not ready after ${timeoutMs}ms`);
49
+ }
50
+ async function startWebServers(configs, projectDir) {
51
+ const started = [];
52
+ for (const cfg of configs) {
53
+ const target = cfg.url ?? (cfg.port ? `http://localhost:${cfg.port}` : undefined);
54
+ if (!target)
55
+ throw new Error(`waygraph: webServer needs "url" or "port"`);
56
+ if (cfg.reuseExistingServer !== false && (await isUp(target)))
57
+ continue;
58
+ // detached = own process group, so stop() kills the shell AND whatever it exec'd.
59
+ const child = spawn(cfg.command, {
60
+ shell: true,
61
+ detached: true,
62
+ cwd: cfg.cwd ? join(projectDir, cfg.cwd) : projectDir,
63
+ env: { ...process.env, ...cfg.env },
64
+ stdio: ["ignore", cfg.stdout === "pipe" ? "inherit" : "ignore", cfg.stderr === "ignore" ? "ignore" : "inherit"],
65
+ });
66
+ started.push(child);
67
+ await waitUntilUp(target, cfg.timeout ?? 60_000);
68
+ }
69
+ return started;
70
+ }
71
+ function stopWebServers(started) {
72
+ for (const child of started) {
73
+ try {
74
+ if (typeof child.pid === "number")
75
+ process.kill(-child.pid, "SIGTERM");
76
+ }
77
+ catch {
78
+ /* already exited */
79
+ }
80
+ }
81
+ }
82
+ /** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
83
+ export async function withWebServer(projectDir, fn) {
84
+ const started = await startWebServers(await loadWebServerConfigs(projectDir), projectDir);
85
+ try {
86
+ return await fn();
87
+ }
88
+ finally {
89
+ stopWebServers(started);
90
+ }
91
+ }
@@ -6,11 +6,11 @@
6
6
  "description": "Waygraph Map folder convention proof - (group)/<page>/page.block.ts + nav.block.ts + methods/*.block.ts, offline fixture, zero new engine code.",
7
7
  "scripts": {
8
8
  "typecheck": "tsc --noEmit",
9
- "test": "npm run fixture:test",
9
+ "test": "playwright test",
10
10
  "fixture": "node scripts/fixture-server.mjs",
11
- "fixture:test": "node scripts/with-fixture.mjs npx playwright test",
12
11
  "graph": "waygraph graph",
13
- "auto:cli": "node scripts/with-fixture.mjs waygraph auto --cli"
12
+ "map": "waygraph map",
13
+ "auto:cli": "waygraph auto --cli"
14
14
  },
15
15
  "waygraph": {
16
16
  "baseUrl": "http://127.0.0.1:4277"
@@ -1,7 +1,5 @@
1
1
  import { defineConfig } from "@playwright/test";
2
-
3
- const PORT = process.env.WAYGRAPH_FIXTURE_PORT || "4277";
4
- const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
2
+ import { chromiumExecutablePath } from "waygraph";
5
3
 
6
4
  export default defineConfig({
7
5
  testDir: "./tests",
@@ -9,13 +7,15 @@ export default defineConfig({
9
7
  workers: 1,
10
8
  timeout: 30_000,
11
9
  reporter: [["list"], ["html", { open: "never" }]],
10
+ webServer: {
11
+ command: "node scripts/fixture-server.mjs",
12
+ url: "http://127.0.0.1:4277/dashboard",
13
+ reuseExistingServer: !process.env.CI,
14
+ },
12
15
  use: {
13
16
  headless: true,
14
- baseURL: process.env.WAYGRAPH_BASE_URL || `http://${HOST}:${PORT}`,
17
+ baseURL: "http://127.0.0.1:4277",
15
18
  trace: "retain-on-failure",
16
- launchOptions: {
17
- executablePath: process.env.CHROME_PATH || process.env.CHROMIUM_PATH,
18
- args: ["--no-sandbox", "--disable-dev-shm-usage"],
19
- },
19
+ launchOptions: { executablePath: chromiumExecutablePath() },
20
20
  },
21
21
  });
@@ -1,37 +1,18 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Tiny static server for this example's offline fixture pages.
4
- * Mirrors templates/scaffold's own scripts/fixture-server.mjs exactly.
5
- */
1
+ // Stands in for this example's real app: serves src/pages/<name>.html at clean URLs (/dashboard, /docs).
2
+ // Started and stopped by playwright.config.ts's webServer - waygraph run/demo/auto/test all honor it.
6
3
  import { createServer } from "node:http";
7
4
  import { readFileSync, existsSync } from "node:fs";
8
- import { join, dirname, extname, normalize } from "node:path";
9
- import { fileURLToPath } from "node:url";
5
+ import { join } from "node:path";
10
6
 
11
- const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../src/pages");
12
- const PORT = Number(process.env.WAYGRAPH_FIXTURE_PORT || 4277);
13
- const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
7
+ const PAGES = join(import.meta.dirname, "../src/pages");
14
8
 
15
- const TYPES = {
16
- ".html": "text/html; charset=utf-8",
17
- };
18
-
19
- const server = createServer((req, res) => {
20
- const raw = (req.url || "/").split("?")[0] || "/";
21
- const rel = raw === "/" ? "dashboard.html" : raw.replace(/^\//, "");
22
- const full = normalize(join(ROOT, rel));
23
- if (!full.startsWith(ROOT) || !existsSync(full)) {
24
- res.writeHead(404, { "content-type": "text/plain" });
25
- res.end("not found");
9
+ createServer((req, res) => {
10
+ const path = (req.url || "/").split("?")[0];
11
+ const name = path === "/" ? "dashboard" : path.slice(1);
12
+ const file = join(PAGES, `${name}.html`);
13
+ if (!/^[a-z-]+$/.test(name) || !existsSync(file)) {
14
+ res.writeHead(404).end("not found");
26
15
  return;
27
16
  }
28
- const type = TYPES[extname(full)] || "application/octet-stream";
29
- res.writeHead(200, { "content-type": type });
30
- res.end(readFileSync(full));
31
- });
32
-
33
- server.listen(PORT, HOST, () => {
34
- if (process.env.WAYGRAPH_FIXTURE_QUIET !== "1") {
35
- console.error(`waygraph fixture: http://${HOST}:${PORT}/dashboard.html`);
36
- }
37
- });
17
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(readFileSync(file));
18
+ }).listen(4277, "127.0.0.1");