@noego/wood 0.4.9 → 0.5.0

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 (493) hide show
  1. package/README.md +118 -42
  2. package/bin/axe.js +313 -98
  3. package/dist/{loader/__fixtures__/layouts/app.load.cjs → automation/actions.cjs} +3 -13
  4. package/dist/automation/actions.cjs.map +1 -0
  5. package/dist/automation/actions.d.cts +57 -0
  6. package/dist/automation/actions.d.ts +57 -0
  7. package/dist/automation/actions.js +1 -0
  8. package/dist/automation/actions.js.map +1 -0
  9. package/dist/automation/actions_executor.cjs +101 -0
  10. package/dist/automation/actions_executor.cjs.map +1 -0
  11. package/dist/automation/actions_executor.d.cts +16 -0
  12. package/dist/automation/actions_executor.d.ts +16 -0
  13. package/dist/automation/actions_executor.js +76 -0
  14. package/dist/automation/actions_executor.js.map +1 -0
  15. package/dist/automation/connection.cjs +86 -0
  16. package/dist/automation/connection.cjs.map +1 -0
  17. package/dist/automation/connection.d.cts +18 -0
  18. package/dist/automation/connection.d.ts +18 -0
  19. package/dist/automation/connection.js +51 -0
  20. package/dist/automation/connection.js.map +1 -0
  21. package/dist/{middleware/__fixtures__/middleware/sequence.cjs → automation/errors.cjs} +25 -22
  22. package/dist/automation/errors.cjs.map +1 -0
  23. package/dist/automation/errors.d.cts +31 -0
  24. package/dist/automation/errors.d.ts +31 -0
  25. package/dist/automation/errors.js +24 -0
  26. package/dist/automation/errors.js.map +1 -0
  27. package/dist/automation/index.cjs +49 -0
  28. package/dist/automation/index.cjs.map +1 -0
  29. package/dist/automation/index.d.cts +16 -0
  30. package/dist/automation/index.d.ts +16 -0
  31. package/dist/automation/index.js +15 -0
  32. package/dist/automation/index.js.map +1 -0
  33. package/dist/automation/introspection_reader.cjs +75 -0
  34. package/dist/automation/introspection_reader.cjs.map +1 -0
  35. package/dist/automation/introspection_reader.d.cts +20 -0
  36. package/dist/automation/introspection_reader.d.ts +20 -0
  37. package/dist/automation/introspection_reader.js +48 -0
  38. package/dist/automation/introspection_reader.js.map +1 -0
  39. package/dist/automation/locator.cjs +102 -0
  40. package/dist/automation/locator.cjs.map +1 -0
  41. package/dist/automation/locator.d.cts +51 -0
  42. package/dist/automation/locator.d.ts +51 -0
  43. package/dist/automation/locator.js +75 -0
  44. package/dist/automation/locator.js.map +1 -0
  45. package/dist/{loader/__fixtures__/views/test/page.load.cjs → automation/observation.cjs} +3 -13
  46. package/dist/automation/observation.cjs.map +1 -0
  47. package/dist/automation/observation.d.cts +44 -0
  48. package/dist/automation/observation.d.ts +44 -0
  49. package/dist/automation/observation.js +1 -0
  50. package/dist/automation/observation.js.map +1 -0
  51. package/dist/{controller/__fixtures__/controllers/test.cjs → automation/receipts.cjs} +3 -15
  52. package/dist/automation/receipts.cjs.map +1 -0
  53. package/dist/automation/receipts.d.cts +27 -0
  54. package/dist/automation/receipts.d.ts +27 -0
  55. package/dist/automation/receipts.js +1 -0
  56. package/dist/automation/receipts.js.map +1 -0
  57. package/dist/automation/scenario.cjs +696 -0
  58. package/dist/automation/scenario.cjs.map +1 -0
  59. package/dist/automation/scenario.d.cts +89 -0
  60. package/dist/automation/scenario.d.ts +89 -0
  61. package/dist/automation/scenario.js +660 -0
  62. package/dist/automation/scenario.js.map +1 -0
  63. package/dist/automation/scrolling.cjs +17 -0
  64. package/dist/automation/scrolling.cjs.map +1 -0
  65. package/dist/automation/scrolling.d.cts +51 -0
  66. package/dist/automation/scrolling.d.ts +51 -0
  67. package/dist/automation/scrolling.js +1 -0
  68. package/dist/automation/scrolling.js.map +1 -0
  69. package/dist/automation/scrolling_executor.cjs +109 -0
  70. package/dist/automation/scrolling_executor.cjs.map +1 -0
  71. package/dist/automation/scrolling_executor.d.cts +13 -0
  72. package/dist/automation/scrolling_executor.d.ts +13 -0
  73. package/dist/automation/scrolling_executor.js +84 -0
  74. package/dist/automation/scrolling_executor.js.map +1 -0
  75. package/dist/automation/target_identity.cjs +17 -0
  76. package/dist/automation/target_identity.cjs.map +1 -0
  77. package/dist/automation/target_identity.d.cts +28 -0
  78. package/dist/automation/target_identity.d.ts +28 -0
  79. package/dist/automation/target_identity.js +1 -0
  80. package/dist/automation/target_identity.js.map +1 -0
  81. package/dist/automation/target_registry.cjs +148 -0
  82. package/dist/automation/target_registry.cjs.map +1 -0
  83. package/dist/automation/target_registry.d.cts +32 -0
  84. package/dist/automation/target_registry.d.ts +32 -0
  85. package/dist/automation/target_registry.js +122 -0
  86. package/dist/automation/target_registry.js.map +1 -0
  87. package/dist/automation/waits.cjs +17 -0
  88. package/dist/automation/waits.cjs.map +1 -0
  89. package/dist/automation/waits.d.cts +44 -0
  90. package/dist/automation/waits.d.ts +44 -0
  91. package/dist/automation/waits.js +1 -0
  92. package/dist/automation/waits.js.map +1 -0
  93. package/dist/automation/waits_executor.cjs +104 -0
  94. package/dist/automation/waits_executor.cjs.map +1 -0
  95. package/dist/automation/waits_executor.d.cts +14 -0
  96. package/dist/automation/waits_executor.d.ts +14 -0
  97. package/dist/automation/waits_executor.js +79 -0
  98. package/dist/automation/waits_executor.js.map +1 -0
  99. package/dist/bridge/backend_bridge.cjs.map +1 -1
  100. package/dist/bridge/backend_bridge.js.map +1 -1
  101. package/dist/client/index.cjs +78 -21
  102. package/dist/client/index.cjs.map +1 -1
  103. package/dist/client/index.d.cts +19 -3
  104. package/dist/client/index.d.ts +19 -3
  105. package/dist/client/index.js +80 -22
  106. package/dist/client/index.js.map +1 -1
  107. package/dist/client/renderer_log_transport.cjs +151 -0
  108. package/dist/client/renderer_log_transport.cjs.map +1 -0
  109. package/dist/client/renderer_log_transport.d.cts +54 -0
  110. package/dist/client/renderer_log_transport.d.ts +54 -0
  111. package/dist/client/renderer_log_transport.js +123 -0
  112. package/dist/client/renderer_log_transport.js.map +1 -0
  113. package/dist/codegen/controller_registration_generator.cjs +13 -2
  114. package/dist/codegen/controller_registration_generator.cjs.map +1 -1
  115. package/dist/codegen/controller_registration_generator.d.cts +12 -1
  116. package/dist/codegen/controller_registration_generator.d.ts +12 -1
  117. package/dist/codegen/controller_registration_generator.js +10 -1
  118. package/dist/codegen/controller_registration_generator.js.map +1 -1
  119. package/dist/codegen/index.d.cts +1 -0
  120. package/dist/codegen/index.d.ts +1 -0
  121. package/dist/codegen/preload_generator.cjs +13 -6
  122. package/dist/codegen/preload_generator.cjs.map +1 -1
  123. package/dist/codegen/preload_generator.d.cts +11 -2
  124. package/dist/codegen/preload_generator.d.ts +11 -2
  125. package/dist/codegen/preload_generator.js +13 -6
  126. package/dist/codegen/preload_generator.js.map +1 -1
  127. package/dist/codegen/renderer_app_generator.cjs +95 -44
  128. package/dist/codegen/renderer_app_generator.cjs.map +1 -1
  129. package/dist/codegen/renderer_app_generator.js +95 -44
  130. package/dist/codegen/renderer_app_generator.js.map +1 -1
  131. package/dist/codegen/type_generator.cjs +1 -0
  132. package/dist/codegen/type_generator.cjs.map +1 -1
  133. package/dist/codegen/type_generator.js +1 -0
  134. package/dist/codegen/type_generator.js.map +1 -1
  135. package/dist/config/config_parser.cjs +95 -4
  136. package/dist/config/config_parser.cjs.map +1 -1
  137. package/dist/config/config_parser.d.cts +10 -2
  138. package/dist/config/config_parser.d.ts +10 -2
  139. package/dist/config/config_parser.js +92 -3
  140. package/dist/config/config_parser.js.map +1 -1
  141. package/dist/config/index.cjs +6 -2
  142. package/dist/config/index.cjs.map +1 -1
  143. package/dist/config/index.d.cts +2 -2
  144. package/dist/config/index.d.ts +2 -2
  145. package/dist/config/index.js +8 -2
  146. package/dist/config/index.js.map +1 -1
  147. package/dist/controller/controller_resolver.cjs +51 -3
  148. package/dist/controller/controller_resolver.cjs.map +1 -1
  149. package/dist/controller/controller_resolver.d.cts +27 -4
  150. package/dist/controller/controller_resolver.d.ts +27 -4
  151. package/dist/controller/controller_resolver.js +48 -2
  152. package/dist/controller/controller_resolver.js.map +1 -1
  153. package/dist/controller/index.cjs +6 -2
  154. package/dist/controller/index.cjs.map +1 -1
  155. package/dist/controller/index.d.cts +1 -1
  156. package/dist/controller/index.d.ts +1 -1
  157. package/dist/controller/index.js +4 -2
  158. package/dist/controller/index.js.map +1 -1
  159. package/dist/dev/wood_dev_server.cjs +4 -1
  160. package/dist/dev/wood_dev_server.cjs.map +1 -1
  161. package/dist/dev/wood_dev_server.js +5 -2
  162. package/dist/dev/wood_dev_server.js.map +1 -1
  163. package/dist/dev/yaml_watcher.cjs +1 -1
  164. package/dist/dev/yaml_watcher.cjs.map +1 -1
  165. package/dist/dev/yaml_watcher.d.cts +4 -0
  166. package/dist/dev/yaml_watcher.d.ts +4 -0
  167. package/dist/dev/yaml_watcher.js +1 -1
  168. package/dist/dev/yaml_watcher.js.map +1 -1
  169. package/dist/frontend/frontend_lifecycle.cjs +74 -0
  170. package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
  171. package/dist/frontend/frontend_lifecycle.d.cts +50 -0
  172. package/dist/frontend/frontend_lifecycle.d.ts +50 -0
  173. package/dist/frontend/frontend_lifecycle.js +50 -0
  174. package/dist/frontend/frontend_lifecycle.js.map +1 -0
  175. package/dist/frontend/frontend_page.cjs +122 -0
  176. package/dist/frontend/frontend_page.cjs.map +1 -0
  177. package/dist/frontend/frontend_page.d.cts +62 -0
  178. package/dist/frontend/frontend_page.d.ts +62 -0
  179. package/dist/frontend/frontend_page.js +98 -0
  180. package/dist/frontend/frontend_page.js.map +1 -0
  181. package/dist/frontend/frontend_surface.cjs +249 -0
  182. package/dist/frontend/frontend_surface.cjs.map +1 -0
  183. package/dist/frontend/frontend_surface.d.cts +64 -0
  184. package/dist/frontend/frontend_surface.d.ts +64 -0
  185. package/dist/frontend/frontend_surface.js +224 -0
  186. package/dist/frontend/frontend_surface.js.map +1 -0
  187. package/dist/frontend/index.cjs +52 -0
  188. package/dist/frontend/index.cjs.map +1 -0
  189. package/dist/frontend/index.d.cts +10 -0
  190. package/dist/frontend/index.d.ts +10 -0
  191. package/dist/frontend/index.js +19 -0
  192. package/dist/frontend/index.js.map +1 -0
  193. package/dist/frontend/page_catalog.cjs +135 -0
  194. package/dist/frontend/page_catalog.cjs.map +1 -0
  195. package/dist/frontend/page_catalog.d.cts +56 -0
  196. package/dist/frontend/page_catalog.d.ts +56 -0
  197. package/dist/frontend/page_catalog.js +108 -0
  198. package/dist/frontend/page_catalog.js.map +1 -0
  199. package/dist/frontend/tracked_transport.cjs +55 -0
  200. package/dist/frontend/tracked_transport.cjs.map +1 -0
  201. package/dist/frontend/tracked_transport.d.cts +36 -0
  202. package/dist/frontend/tracked_transport.d.ts +36 -0
  203. package/dist/frontend/tracked_transport.js +31 -0
  204. package/dist/frontend/tracked_transport.js.map +1 -0
  205. package/dist/frontend/work_registry.cjs +153 -0
  206. package/dist/frontend/work_registry.cjs.map +1 -0
  207. package/dist/frontend/work_registry.d.cts +70 -0
  208. package/dist/frontend/work_registry.d.ts +70 -0
  209. package/dist/frontend/work_registry.js +128 -0
  210. package/dist/frontend/work_registry.js.map +1 -0
  211. package/dist/index.cjs +24 -0
  212. package/dist/index.cjs.map +1 -1
  213. package/dist/index.d.cts +11 -7
  214. package/dist/index.d.ts +11 -7
  215. package/dist/index.js +27 -4
  216. package/dist/index.js.map +1 -1
  217. package/dist/main/index.cjs +10 -0
  218. package/dist/main/index.cjs.map +1 -1
  219. package/dist/main/index.d.cts +14 -2
  220. package/dist/main/index.d.ts +14 -2
  221. package/dist/main/index.js +16 -0
  222. package/dist/main/index.js.map +1 -1
  223. package/dist/middleware/middleware_resolver.cjs +22 -1
  224. package/dist/middleware/middleware_resolver.cjs.map +1 -1
  225. package/dist/middleware/middleware_resolver.d.cts +13 -1
  226. package/dist/middleware/middleware_resolver.d.ts +13 -1
  227. package/dist/middleware/middleware_resolver.js +22 -1
  228. package/dist/middleware/middleware_resolver.js.map +1 -1
  229. package/dist/navigation/automation_introspection.cjs +110 -0
  230. package/dist/navigation/automation_introspection.cjs.map +1 -0
  231. package/dist/navigation/automation_introspection.d.cts +60 -0
  232. package/dist/navigation/automation_introspection.d.ts +60 -0
  233. package/dist/navigation/automation_introspection.js +85 -0
  234. package/dist/navigation/automation_introspection.js.map +1 -0
  235. package/dist/navigation/index.cjs +10 -2
  236. package/dist/navigation/index.cjs.map +1 -1
  237. package/dist/navigation/index.d.cts +27 -1
  238. package/dist/navigation/index.d.ts +27 -1
  239. package/dist/navigation/index.js +6 -1
  240. package/dist/navigation/index.js.map +1 -1
  241. package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
  242. package/dist/navigation/layout_preservation.cjs.map +1 -0
  243. package/dist/navigation/layout_preservation.d.cts +2 -0
  244. package/dist/navigation/layout_preservation.d.ts +2 -0
  245. package/dist/navigation/layout_preservation.js +18 -0
  246. package/dist/navigation/layout_preservation.js.map +1 -0
  247. package/dist/parser/index.cjs +2 -0
  248. package/dist/parser/index.cjs.map +1 -1
  249. package/dist/parser/index.d.cts +1 -1
  250. package/dist/parser/index.d.ts +1 -1
  251. package/dist/parser/index.js +2 -1
  252. package/dist/parser/index.js.map +1 -1
  253. package/dist/parser/operations_parser.cjs +6 -0
  254. package/dist/parser/operations_parser.cjs.map +1 -1
  255. package/dist/parser/operations_parser.d.cts +9 -2
  256. package/dist/parser/operations_parser.d.ts +9 -2
  257. package/dist/parser/operations_parser.js +5 -0
  258. package/dist/parser/operations_parser.js.map +1 -1
  259. package/dist/parser/views_parser.cjs.map +1 -1
  260. package/dist/parser/views_parser.js.map +1 -1
  261. package/dist/router/index.d.cts +1 -0
  262. package/dist/router/index.d.ts +1 -0
  263. package/dist/router/wood_router.cjs +35 -3
  264. package/dist/router/wood_router.cjs.map +1 -1
  265. package/dist/router/wood_router.d.cts +15 -0
  266. package/dist/router/wood_router.d.ts +15 -0
  267. package/dist/router/wood_router.js +36 -4
  268. package/dist/router/wood_router.js.map +1 -1
  269. package/dist/runtime/get_container.cjs +9 -34
  270. package/dist/runtime/get_container.cjs.map +1 -1
  271. package/dist/runtime/get_container.d.cts +24 -4
  272. package/dist/runtime/get_container.d.ts +24 -4
  273. package/dist/runtime/get_container.js +8 -23
  274. package/dist/runtime/get_container.js.map +1 -1
  275. package/dist/runtime/index.cjs +9 -0
  276. package/dist/runtime/index.cjs.map +1 -1
  277. package/dist/runtime/index.d.cts +5 -2
  278. package/dist/runtime/index.d.ts +5 -2
  279. package/dist/runtime/index.js +10 -1
  280. package/dist/runtime/index.js.map +1 -1
  281. package/dist/runtime/renderer_config_extension.cjs +50 -0
  282. package/dist/runtime/renderer_config_extension.cjs.map +1 -0
  283. package/dist/runtime/renderer_config_extension.d.cts +19 -0
  284. package/dist/runtime/renderer_config_extension.d.ts +19 -0
  285. package/dist/runtime/renderer_config_extension.js +24 -0
  286. package/dist/runtime/renderer_config_extension.js.map +1 -0
  287. package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
  288. package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
  289. package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
  290. package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
  291. package/dist/runtime/renderer_log_batch_receiver.js +48 -0
  292. package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
  293. package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
  294. package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
  295. package/dist/runtime/runtime.cjs +14 -0
  296. package/dist/runtime/runtime.cjs.map +1 -1
  297. package/dist/runtime/runtime.d.cts +2 -1
  298. package/dist/runtime/runtime.d.ts +2 -1
  299. package/dist/runtime/runtime.js +14 -0
  300. package/dist/runtime/runtime.js.map +1 -1
  301. package/dist/stick/index.cjs.map +1 -1
  302. package/dist/stick/index.js.map +1 -1
  303. package/dist/testing/automation_assertions.cjs +417 -0
  304. package/dist/testing/automation_assertions.cjs.map +1 -0
  305. package/dist/testing/automation_assertions.d.cts +44 -0
  306. package/dist/testing/automation_assertions.d.ts +44 -0
  307. package/dist/testing/automation_assertions.js +385 -0
  308. package/dist/testing/automation_assertions.js.map +1 -0
  309. package/dist/testing/browser.cjs +130 -57
  310. package/dist/testing/browser.cjs.map +1 -1
  311. package/dist/testing/browser.d.cts +10 -4
  312. package/dist/testing/browser.d.ts +10 -4
  313. package/dist/testing/browser.js +132 -53
  314. package/dist/testing/browser.js.map +1 -1
  315. package/dist/testing/create_controller_harness.cjs +28 -8
  316. package/dist/testing/create_controller_harness.cjs.map +1 -1
  317. package/dist/testing/create_controller_harness.d.cts +18 -2
  318. package/dist/testing/create_controller_harness.d.ts +18 -2
  319. package/dist/testing/create_controller_harness.js +28 -8
  320. package/dist/testing/create_controller_harness.js.map +1 -1
  321. package/dist/testing/create_router_bridge.d.cts +1 -0
  322. package/dist/testing/create_router_bridge.d.ts +1 -0
  323. package/dist/testing/create_test_router.d.cts +1 -0
  324. package/dist/testing/create_test_router.d.ts +1 -0
  325. package/dist/testing/geometry.cjs +109 -0
  326. package/dist/testing/geometry.cjs.map +1 -0
  327. package/dist/testing/geometry.d.cts +45 -0
  328. package/dist/testing/geometry.d.ts +45 -0
  329. package/dist/testing/geometry.js +79 -0
  330. package/dist/testing/geometry.js.map +1 -0
  331. package/dist/testing/index.cjs +62 -2
  332. package/dist/testing/index.cjs.map +1 -1
  333. package/dist/testing/index.d.cts +23 -4
  334. package/dist/testing/index.d.ts +23 -4
  335. package/dist/testing/index.js +50 -2
  336. package/dist/testing/index.js.map +1 -1
  337. package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
  338. package/dist/testing/test_wood.cjs.map +1 -0
  339. package/dist/testing/test_wood.d.cts +16 -0
  340. package/dist/testing/test_wood.d.ts +16 -0
  341. package/dist/testing/test_wood.js +12 -0
  342. package/dist/testing/test_wood.js.map +1 -0
  343. package/dist/testing/test_wood_config.cjs +272 -0
  344. package/dist/testing/test_wood_config.cjs.map +1 -0
  345. package/dist/testing/test_wood_config.d.cts +111 -0
  346. package/dist/testing/test_wood_config.d.ts +111 -0
  347. package/dist/testing/test_wood_config.js +247 -0
  348. package/dist/testing/test_wood_config.js.map +1 -0
  349. package/dist/testing/wood_config_source.cjs +146 -0
  350. package/dist/testing/wood_config_source.cjs.map +1 -0
  351. package/dist/testing/wood_config_source.d.cts +36 -0
  352. package/dist/testing/wood_config_source.d.ts +36 -0
  353. package/dist/testing/wood_config_source.js +112 -0
  354. package/dist/testing/wood_config_source.js.map +1 -0
  355. package/dist/testing/wood_env_renderer.cjs +210 -0
  356. package/dist/testing/wood_env_renderer.cjs.map +1 -0
  357. package/dist/testing/wood_env_renderer.d.cts +74 -0
  358. package/dist/testing/wood_env_renderer.d.ts +74 -0
  359. package/dist/testing/wood_env_renderer.js +188 -0
  360. package/dist/testing/wood_env_renderer.js.map +1 -0
  361. package/dist/testing/wood_test_selection.cjs +94 -0
  362. package/dist/testing/wood_test_selection.cjs.map +1 -0
  363. package/dist/testing/wood_test_selection.d.cts +39 -0
  364. package/dist/testing/wood_test_selection.d.ts +39 -0
  365. package/dist/testing/wood_test_selection.js +68 -0
  366. package/dist/testing/wood_test_selection.js.map +1 -0
  367. package/dist/trace-testing/index.d.cts +1 -2
  368. package/dist/trace-testing/index.d.ts +1 -2
  369. package/dist/trace-testing/trace_recorder.cjs +1 -1
  370. package/dist/trace-testing/trace_recorder.cjs.map +1 -1
  371. package/dist/trace-testing/trace_recorder.d.cts +1 -2
  372. package/dist/trace-testing/trace_recorder.d.ts +1 -2
  373. package/dist/trace-testing/trace_recorder.js +1 -1
  374. package/dist/trace-testing/trace_recorder.js.map +1 -1
  375. package/dist/trace-transport/index.d.cts +1 -1
  376. package/dist/trace-transport/index.d.ts +1 -1
  377. package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
  378. package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
  379. package/dist/tracing/index.cjs +9 -2
  380. package/dist/tracing/index.cjs.map +1 -1
  381. package/dist/tracing/index.d.cts +3 -2
  382. package/dist/tracing/index.d.ts +3 -2
  383. package/dist/tracing/index.js +7 -1
  384. package/dist/tracing/index.js.map +1 -1
  385. package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
  386. package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
  387. package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
  388. package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
  389. package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
  390. package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
  391. package/dist/tracing/renderer_trace_batch_transport.js +48 -6
  392. package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
  393. package/dist/tracing/trace_batch_adapter.cjs +110 -0
  394. package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
  395. package/dist/tracing/trace_batch_adapter.d.cts +36 -0
  396. package/dist/tracing/trace_batch_adapter.d.ts +36 -0
  397. package/dist/tracing/trace_batch_adapter.js +86 -0
  398. package/dist/tracing/trace_batch_adapter.js.map +1 -0
  399. package/dist/tracing/trace_commit_writer.d.cts +1 -1
  400. package/dist/tracing/trace_commit_writer.d.ts +1 -1
  401. package/dist/tracing/trace_hub.cjs +87 -20
  402. package/dist/tracing/trace_hub.cjs.map +1 -1
  403. package/dist/tracing/trace_hub.d.cts +1 -1
  404. package/dist/tracing/trace_hub.d.ts +1 -1
  405. package/dist/tracing/trace_hub.js +85 -20
  406. package/dist/tracing/trace_hub.js.map +1 -1
  407. package/dist/tracing/trace_provider.cjs +21 -6
  408. package/dist/tracing/trace_provider.cjs.map +1 -1
  409. package/dist/tracing/trace_provider.d.cts +13 -4
  410. package/dist/tracing/trace_provider.d.ts +13 -4
  411. package/dist/tracing/trace_provider.js +22 -7
  412. package/dist/tracing/trace_provider.js.map +1 -1
  413. package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
  414. package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
  415. package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
  416. package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
  417. package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
  418. package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
  419. package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
  420. package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
  421. package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
  422. package/dist/tracing/wood_trace_batch_contract.js +2 -0
  423. package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
  424. package/dist/transport/build_transport_bridge.cjs +4 -2
  425. package/dist/transport/build_transport_bridge.cjs.map +1 -1
  426. package/dist/transport/build_transport_bridge.d.cts +7 -1
  427. package/dist/transport/build_transport_bridge.d.ts +7 -1
  428. package/dist/transport/build_transport_bridge.js +2 -1
  429. package/dist/transport/build_transport_bridge.js.map +1 -1
  430. package/dist/transport/in_process_router_transport.d.cts +1 -0
  431. package/dist/transport/in_process_router_transport.d.ts +1 -0
  432. package/dist/transport/index.d.cts +1 -0
  433. package/dist/transport/index.d.ts +1 -0
  434. package/dist/types/config.cjs.map +1 -1
  435. package/dist/types/config.d.cts +47 -1
  436. package/dist/types/config.d.ts +47 -1
  437. package/dist/types/context.cjs +12 -0
  438. package/dist/types/context.cjs.map +1 -1
  439. package/dist/types/context.d.cts +27 -1
  440. package/dist/types/context.d.ts +27 -1
  441. package/dist/types/context.js +4 -0
  442. package/dist/types/context.js.map +1 -1
  443. package/dist/types/index.d.cts +2 -2
  444. package/dist/types/index.d.ts +2 -2
  445. package/dist/types/operations.cjs.map +1 -1
  446. package/dist/types/operations.d.cts +2 -0
  447. package/dist/types/operations.d.ts +2 -0
  448. package/docs/axe.md +706 -0
  449. package/package.json +19 -5
  450. package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
  451. package/src/components/NavigationShell.svelte +126 -49
  452. package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
  453. package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
  454. package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
  455. package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
  456. package/dist/controller/__fixtures__/controllers/chat.js +0 -12
  457. package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
  458. package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
  459. package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
  460. package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
  461. package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
  462. package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
  463. package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
  464. package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
  465. package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
  466. package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
  467. package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
  468. package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
  469. package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
  470. package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
  471. package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
  472. package/dist/controller/__fixtures__/controllers/test.js +0 -9
  473. package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
  474. package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
  475. package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
  476. package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
  477. package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
  478. package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
  479. package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
  480. package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
  481. package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
  482. package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
  483. package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
  484. package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
  485. package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
  486. package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
  487. package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
  488. package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
  489. package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
  490. package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
  491. package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
  492. package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
  493. package/dist/middleware/__fixtures__/middleware/sequence.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/main/index.ts"],"sourcesContent":["import path from 'path';\nimport {\n app as electronApp,\n BrowserWindow,\n ipcMain,\n MessageChannelMain,\n Menu,\n protocol,\n net,\n shell,\n screen,\n} from 'electron';\nimport type {\n BrowserWindowConstructorOptions,\n BrowserWindow as ElectronBrowserWindow,\n Event as ElectronEvent,\n IpcMainInvokeEvent,\n Privileges,\n RenderProcessGoneDetails,\n} from 'electron';\nimport { getLogger } from '@noego/logger';\nimport { WindowStateStore } from '../window/window_state_store.js';\nimport { getContainer } from '../runtime/get_container.js';\nimport { runtime as bootRuntime } from '../runtime/runtime.js';\nimport { dispatchRendererTracePayload, type TraceLevel } from '../tracing/index.js';\nimport { setApplicationRoot } from '../runtime/application_root.js';\nimport type { RegisterRuntimeRouter } from '../runtime/runtime.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogCallback,\n} from '../runtime/renderer_log_dispatcher.js';\nimport { Ipc, getIpc } from '../ipc/index.js';\nimport { setIpcPushSender, clearIpcPushSender, type IpcPushOptions } from '../ipc/shared.js';\nimport {\n drainRendererTracesBeforeQuit,\n RendererTraceDrainCoordinator,\n} from './renderer_trace_drain_coordinator.js';\n\ntype CleanupHandler = () => void | Promise<void>;\n\nexport type BootstrapActivationState = 'pending' | 'ready' | 'failed';\n\n/**\n * Owns the startup/activation boundary so Electron activation cannot create a\n * renderer until bootstrap has registered the runtime IPC handlers.\n */\nexport class BootstrapActivationGate {\n private currentState: BootstrapActivationState = 'pending';\n\n constructor(\n private readonly hasWindow: () => boolean,\n private readonly createMainWindow: () => void,\n ) {}\n\n get state(): BootstrapActivationState {\n return this.currentState;\n }\n\n activate(): void {\n if (this.currentState === 'ready' && !this.hasWindow()) {\n this.createMainWindow();\n }\n }\n\n ready(): void {\n if (this.currentState !== 'pending') {\n return;\n }\n\n // createMainWindow may throw. Leave the gate pending so the bootstrap\n // rejection can make the failure terminal rather than exposing readiness.\n this.createMainWindow();\n this.currentState = 'ready';\n }\n\n failed(): void {\n if (this.currentState === 'pending') {\n this.currentState = 'failed';\n }\n }\n}\n\nexport type RendererHealthState =\n | 'ready'\n | 'loading'\n | 'unresponsive'\n | 'gone'\n | 'destroyed';\n\nexport type WoodWindowConfig = {\n title: string;\n width: number;\n height: number;\n defaultRoute?: string;\n frame?: boolean;\n transparent?: boolean;\n resizable?: boolean;\n alwaysOnTop?: boolean;\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n show?: boolean;\n parent?: string;\n modal?: boolean;\n vibrancy?: string;\n backgroundMaterial?: string;\n backgroundColor?: string;\n rememberBounds?: boolean;\n contextMenu?: 'native' | 'custom';\n acceptFirstMouse?: boolean;\n nativeQuitFallback?: boolean;\n titleBarStyle?: 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover';\n trafficLightPosition?: { x: number; y: number };\n titleBarOverlay?: boolean | { color?: string; symbolColor?: string; height?: number };\n};\n\nexport type PrivilegedSchemeRegistration = {\n scheme: string;\n privileges: Privileges;\n};\n\nexport interface WoodMainAppBootResult {\n scope?: string;\n configureContainer?: (container: any) => void;\n registerSchemesAsPrivileged?: PrivilegedSchemeRegistration[];\n}\n\nexport interface WoodMainBootContext {\n electron: {\n app: typeof electronApp;\n BrowserWindow: typeof BrowserWindow;\n ipcMain: typeof ipcMain;\n protocol: typeof protocol;\n net: typeof net;\n shell: typeof shell;\n screen: typeof screen;\n Menu: typeof Menu;\n };\n logger: ReturnType<typeof getLogger>;\n}\n\nexport function shouldDeferLastWindowCloseForCleanup(\n trackedWindowCount: number,\n cleanupComplete: boolean,\n): boolean {\n return trackedWindowCount === 1 && !cleanupComplete;\n}\n\nexport interface WoodMainRuntimeContext extends WoodMainBootContext {\n container: any;\n applicationRoot: string;\n getWindow: (windowId: string) => ElectronBrowserWindow | null;\n createWindow: (windowId?: string) => ElectronBrowserWindow;\n navigateWindow: (windowId: string, route: string) => Promise<void>;\n broadcast: (channel: string, data: unknown) => void;\n /**\n * Dispatch a channel through the SAME real WoodRouter the ipcMain handlers\n * wrap — full operations-YAML schema validation, controllers, middleware.\n * Available only after the runtime finishes booting (mainBoot runs before the\n * router is constructed, so callers must invoke this lazily, not during\n * mainBoot). This is the in-main seam the launch-flag-gated test control plane\n * uses for driver `api.call`; production code never calls it.\n */\n dispatch: (channel: string, payload?: unknown) => Promise<unknown>;\n getRendererHealthState: (windowId: string) => RendererHealthState | null;\n setRendererLogCallback: (callback: RendererLogCallback | null) => void;\n getRendererLogCallback: () => RendererLogCallback | null;\n getDebugMetadata: () => WoodDebugMetadata;\n}\n\nexport interface WoodRendererHealthEvent {\n windowId: string;\n state: RendererHealthState;\n previousState: RendererHealthState | null;\n webContentsId?: number;\n reason?: string;\n exitCode?: number;\n}\n\nexport type WoodWindowLifecycleContext = WoodMainRuntimeContext;\n\nexport interface StartWoodMainOptions {\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n windowDefs: Record<string, WoodWindowConfig>;\n controllersDir: string;\n middlewareDir: string;\n outDir?: string;\n scope?: string;\n configureContainer?: (container: any) => void;\n appBoot?: (\n context: WoodMainBootContext,\n ) => void | WoodMainAppBootResult | Promise<void | WoodMainAppBootResult>;\n mainBoot?: (\n appBootResult: unknown,\n context: WoodMainRuntimeContext,\n ) => void | CleanupHandler | Promise<void | CleanupHandler>;\n onBeforeQuit?: (context: WoodMainRuntimeContext) => void | Promise<void>;\n onWindowCreated?: (\n windowId: string,\n win: ElectronBrowserWindow,\n context: WoodMainRuntimeContext,\n ) => void | Promise<void>;\n onRendererHealthChanged?: (\n event: WoodRendererHealthEvent,\n context: WoodMainRuntimeContext,\n ) => void | Promise<void>;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n traceTransport?: 'ipc' | 'messageport';\n}\n\nexport interface WoodDebugWindowMetadata {\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: RendererHealthState;\n}\n\nexport interface WoodDebugMetadata {\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: WoodDebugWindowMetadata[];\n}\n\nconst DEFAULT_WOOD_REMOTE_DEBUGGING_PORT = 9333;\n\nexport function resolveWoodDebugMetadataConfiguration(env: NodeJS.ProcessEnv = process.env): {\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n} {\n const isDevelopment = env.WOOD_MODE === 'development';\n if (!isDevelopment) {\n return {\n enabled: false,\n mode: 'production',\n };\n }\n\n const rawPort = env.WOOD_REMOTE_DEBUGGING_PORT;\n const parsedPort = rawPort ? Number.parseInt(rawPort, 10) : DEFAULT_WOOD_REMOTE_DEBUGGING_PORT;\n const port = Number.isFinite(parsedPort) && parsedPort > 0\n ? parsedPort\n : DEFAULT_WOOD_REMOTE_DEBUGGING_PORT;\n\n return {\n enabled: true,\n mode: 'development',\n port,\n };\n}\n\nfunction resolveWindowDef(\n windowDefs: Record<string, WoodWindowConfig>,\n windowId = 'main',\n): WoodWindowConfig {\n const def = windowDefs[windowId];\n if (!def) {\n throw new Error(`Window \"${windowId}\" not defined in generated window defs.`);\n }\n return def;\n}\n\nfunction resolveRuntimePath(relativeOrAbsolutePath: string): string {\n if (path.isAbsolute(relativeOrAbsolutePath)) {\n return relativeOrAbsolutePath;\n }\n return path.join(electronApp.getAppPath(), relativeOrAbsolutePath);\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function startWoodMain(options: StartWoodMainOptions): void {\n const logger = getLogger('wood:main').named('bootstrap');\n const runtimeLogger = getLogger('wood:main').named('runtime');\n const debugConfig = resolveWoodDebugMetadataConfiguration();\n const windowState = new WindowStateStore();\n const windows = new Map<string, ElectronBrowserWindow>();\n const rendererHealth = new Map<string, RendererHealthState>();\n let mainWindow: ElectronBrowserWindow | null = null;\n let beforeQuitCleanupComplete = false;\n let beforeQuitCleanupPromise: Promise<void> | null = null;\n let runtimeContext: WoodMainRuntimeContext | null = null;\n let mainBootCleanup: CleanupHandler | undefined;\n let nativeQuitFallbackInstalled = false;\n const rendererTraceDrain = new RendererTraceDrainCoordinator(ipcMain);\n rendererTraceDrain.start();\n\n for (const stream of [process.stdout, process.stderr]) {\n stream.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') {\n return;\n }\n throw error;\n });\n }\n\n if (debugConfig.enabled && debugConfig.port) {\n electronApp.commandLine.appendSwitch('remote-debugging-port', String(debugConfig.port));\n electronApp.commandLine.appendSwitch('remote-debugging-address', '127.0.0.1');\n logger.info('devtools remote debugging enabled', {\n port: debugConfig.port,\n mode: debugConfig.mode,\n });\n }\n\n const bootContext: WoodMainBootContext = {\n electron: {\n app: electronApp,\n BrowserWindow,\n ipcMain,\n protocol,\n net,\n shell,\n screen,\n Menu,\n },\n logger,\n };\n\n const initializeRuntime = async (): Promise<void> => {\n const appBootResult = options.appBoot\n ? await options.appBoot(bootContext)\n : undefined;\n\n const bootOverrides = (appBootResult ?? {}) as WoodMainAppBootResult;\n const scope = bootOverrides.scope ?? options.scope ?? process.cwd();\n const configureContainer = bootOverrides.configureContainer ?? options.configureContainer;\n const privilegedSchemes = Array.isArray(bootOverrides.registerSchemesAsPrivileged)\n ? bootOverrides.registerSchemesAsPrivileged\n : [];\n\n if (privilegedSchemes.length > 0) {\n protocol.registerSchemesAsPrivileged(privilegedSchemes);\n logger.info('registered privileged schemes', {\n count: privilegedSchemes.length,\n schemes: privilegedSchemes.map((entry) => entry.scheme),\n });\n }\n\n const outDir = options.outDir ?? 'out';\n const preloadPath = path.join(electronApp.getAppPath(), outDir, 'preload', 'index.js');\n const rendererFile = path.join(electronApp.getAppPath(), outDir, 'renderer', 'index.html');\n\n const container = getContainer({\n scope,\n ...(configureContainer ? { configure: configureContainer } : {}),\n });\n\n const registrationContainer = container as {\n registerFunction?: (\n token: any,\n resolver: (...args: any[]) => unknown,\n options?: Record<string, unknown>,\n ) => void;\n };\n\n if (typeof registrationContainer.registerFunction === 'function') {\n registrationContainer.registerFunction(Ipc, () => getIpc());\n }\n\n const getWindow = (windowId: string): ElectronBrowserWindow | null => {\n const existing = windows.get(windowId);\n if (!existing) {\n return null;\n }\n if (existing.isDestroyed()) {\n windows.delete(windowId);\n return null;\n }\n return existing;\n };\n\n const findWindowIdByWebContents = (webContentsId: number): string | null => {\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n if (win.webContents.id === webContentsId) {\n return windowId;\n }\n }\n return null;\n };\n\n const getRendererHealthState = (windowId: string): RendererHealthState | null => {\n return rendererHealth.get(windowId) ?? null;\n };\n\n const notifyRendererHealthChanged = (event: WoodRendererHealthEvent): void => {\n if (!options.onRendererHealthChanged) {\n return;\n }\n if (!runtimeContext) {\n runtimeLogger.warn('renderer health hook skipped before runtime context', {\n windowId: event.windowId,\n state: event.state,\n });\n return;\n }\n\n Promise.resolve(options.onRendererHealthChanged(event, runtimeContext)).catch((error) => {\n runtimeLogger.warn('renderer health hook failed', {\n windowId: event.windowId,\n state: event.state,\n error: toErrorMessage(error),\n });\n });\n };\n\n const setRendererHealth = (\n windowId: string,\n state: RendererHealthState,\n details: {\n webContentsId?: number;\n reason?: string;\n exitCode?: number;\n } = {},\n ): void => {\n const previousState = rendererHealth.get(windowId) ?? null;\n rendererHealth.set(windowId, state);\n notifyRendererHealthChanged({\n windowId,\n state,\n previousState,\n ...details,\n });\n };\n\n const attachRendererHealth = (windowId: string, win: ElectronBrowserWindow): void => {\n const healthLogger = getLogger('wood:main').named(`renderer-health:${windowId}`);\n const webContentsId = win.webContents.id;\n\n setRendererHealth(windowId, 'loading', { webContentsId });\n\n win.webContents.on('did-start-loading', () => {\n setRendererHealth(windowId, 'loading', { webContentsId });\n healthLogger.info('renderer loading', { windowId, webContentsId });\n });\n\n win.webContents.on('did-finish-load', () => {\n setRendererHealth(windowId, 'ready', { webContentsId });\n healthLogger.info('renderer ready', { windowId, webContentsId });\n });\n\n win.webContents.on('unresponsive', () => {\n setRendererHealth(windowId, 'unresponsive', { webContentsId });\n healthLogger.error('renderer unresponsive', { windowId, webContentsId });\n });\n\n win.webContents.on('responsive', () => {\n setRendererHealth(windowId, 'ready', { webContentsId });\n healthLogger.info('renderer responsive', { windowId, webContentsId });\n });\n\n win.webContents.on('render-process-gone', (_event, details: RenderProcessGoneDetails) => {\n setRendererHealth(windowId, 'gone', {\n webContentsId,\n reason: details.reason,\n exitCode: details.exitCode,\n });\n healthLogger.error('renderer process gone', {\n windowId,\n webContentsId,\n reason: details.reason,\n exitCode: details.exitCode,\n });\n });\n\n win.webContents.on('destroyed', () => {\n setRendererHealth(windowId, 'destroyed');\n healthLogger.warn('renderer destroyed', { windowId, webContentsId });\n });\n\n win.on('closed', () => {\n setRendererHealth(windowId, 'destroyed');\n rendererHealth.delete(windowId);\n });\n };\n\n const canSendToWindow = (win: ElectronBrowserWindow): boolean => {\n if (win.isDestroyed()) {\n return false;\n }\n if (win.webContents.isDestroyed()) {\n return false;\n }\n if (typeof win.webContents.isCrashed === 'function' && win.webContents.isCrashed()) {\n return false;\n }\n return true;\n };\n\n const safeSend = (\n windowId: string,\n win: ElectronBrowserWindow,\n channel: string,\n data: unknown,\n ): boolean => {\n if (!canSendToWindow(win)) {\n runtimeLogger.warn('skipping send to unhealthy renderer', {\n windowId,\n channel,\n rendererHealth: getRendererHealthState(windowId),\n });\n return false;\n }\n\n try {\n win.webContents.send(channel, data);\n return true;\n } catch (error) {\n runtimeLogger.warn('send to renderer failed', {\n windowId,\n channel,\n rendererHealth: getRendererHealthState(windowId),\n error: toErrorMessage(error),\n });\n return false;\n }\n };\n\n const installNativeQuitFallback = (): void => {\n if (nativeQuitFallbackInstalled) {\n return;\n }\n Menu.setApplicationMenu(Menu.buildFromTemplate([\n {\n label: electronApp.name,\n submenu: [\n { role: 'quit' },\n ],\n },\n ]));\n nativeQuitFallbackInstalled = true;\n logger.info('native quit fallback installed');\n };\n\n const waitForWindowReady = async (win: ElectronBrowserWindow): Promise<void> => {\n const webContents = win.webContents as ElectronBrowserWindow['webContents'] & {\n isLoadingMainFrame?: () => boolean;\n };\n const isLoading = typeof webContents.isLoadingMainFrame === 'function'\n ? webContents.isLoadingMainFrame()\n : webContents.isLoading();\n if (!isLoading) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n webContents.once('did-finish-load', () => resolve());\n });\n };\n\n const getDebugMetadata = (): WoodDebugMetadata => {\n const debugWindows: WoodDebugWindowMetadata[] = [];\n\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n\n debugWindows.push({\n windowId,\n title: win.getTitle(),\n webContentsId: win.webContents.id,\n url: win.webContents.getURL(),\n focused: win.isFocused(),\n rendererHealth: getRendererHealthState(windowId) ?? undefined,\n });\n }\n\n return {\n ok: true,\n enabled: debugConfig.enabled,\n mode: debugConfig.mode,\n ...(debugConfig.port ? { port: debugConfig.port } : {}),\n windows: debugWindows,\n };\n };\n\n const createWindow = (windowId = 'main'): ElectronBrowserWindow => {\n const existing = getWindow(windowId);\n if (existing) {\n existing.show();\n existing.focus();\n return existing;\n }\n\n const windowDef = resolveWindowDef(options.windowDefs, windowId);\n const defaultShow = windowDef.show ?? true;\n const parentWindow = windowDef.parent ? getWindow(windowDef.parent) : null;\n\n if (windowDef.nativeQuitFallback === true) {\n installNativeQuitFallback();\n }\n\n windowState.setScreen(screen);\n const savedBounds = windowDef.rememberBounds ? windowState.getBounds(windowId) : null;\n\n const windowOptions: BrowserWindowConstructorOptions = {\n width: savedBounds?.width ?? windowDef.width,\n height: savedBounds?.height ?? windowDef.height,\n ...(savedBounds ? { x: savedBounds.x, y: savedBounds.y } : {}),\n ...(windowDef.minWidth != null ? { minWidth: windowDef.minWidth } : {}),\n ...(windowDef.minHeight != null ? { minHeight: windowDef.minHeight } : {}),\n ...(windowDef.maxWidth != null ? { maxWidth: windowDef.maxWidth } : {}),\n ...(windowDef.maxHeight != null ? { maxHeight: windowDef.maxHeight } : {}),\n ...(typeof windowDef.modal === 'boolean' ? { modal: windowDef.modal } : {}),\n ...(parentWindow ? { parent: parentWindow } : {}),\n title: windowDef.title,\n frame: windowDef.frame ?? true,\n transparent: windowDef.transparent ?? false,\n resizable: windowDef.resizable ?? true,\n alwaysOnTop: windowDef.alwaysOnTop ?? false,\n ...(typeof windowDef.backgroundColor === 'string' ? { backgroundColor: windowDef.backgroundColor } : {}),\n ...(process.platform === 'darwin' && typeof windowDef.vibrancy === 'string'\n ? {\n vibrancy: windowDef.vibrancy as BrowserWindowConstructorOptions['vibrancy'],\n visualEffectState: 'active' as const,\n }\n : {}),\n ...(process.platform === 'win32' && typeof windowDef.backgroundMaterial === 'string'\n ? {\n backgroundMaterial: windowDef.backgroundMaterial as BrowserWindowConstructorOptions['backgroundMaterial'],\n }\n : {}),\n ...(typeof windowDef.acceptFirstMouse === 'boolean' ? { acceptFirstMouse: windowDef.acceptFirstMouse } : {}),\n // Hidden title bar with native window controls: macOS draws the\n // traffic lights (positionable), Windows draws min/max/close via the\n // Window Controls Overlay (always top-right; styled via titleBarOverlay).\n ...(typeof windowDef.titleBarStyle === 'string'\n ? { titleBarStyle: windowDef.titleBarStyle as BrowserWindowConstructorOptions['titleBarStyle'] }\n : {}),\n ...(process.platform === 'darwin' && windowDef.trafficLightPosition\n ? { trafficLightPosition: windowDef.trafficLightPosition }\n : {}),\n ...(process.platform === 'win32' && windowDef.titleBarOverlay != null\n ? { titleBarOverlay: windowDef.titleBarOverlay }\n : {}),\n show: savedBounds ? false : defaultShow,\n webPreferences: {\n preload: preloadPath,\n contextIsolation: true,\n nodeIntegration: false,\n },\n };\n\n const win = new BrowserWindow(windowOptions);\n windows.set(windowId, win);\n attachRendererHealth(windowId, win);\n if (windowId === 'main') {\n mainWindow = win;\n }\n\n if (savedBounds?.isMaximized) {\n win.maximize();\n } else if (savedBounds?.isFullScreen) {\n win.setFullScreen(true);\n }\n\n if (savedBounds && defaultShow) {\n win.show();\n }\n\n if (windowDef.rememberBounds) {\n const captureNormalBounds = () => {\n if (!win.isMaximized() && !win.isFullScreen()) {\n const rect = win.getBounds();\n windowState.updateBoundsDebounced(windowId, {\n ...rect,\n isMaximized: false,\n isFullScreen: false,\n });\n }\n };\n win.on('move', captureNormalBounds);\n win.on('resize', captureNormalBounds);\n win.on('close', () => {\n const rect = win.getBounds();\n windowState.saveBoundsSync(windowId, {\n ...rect,\n isMaximized: win.isMaximized(),\n isFullScreen: win.isFullScreen(),\n });\n });\n }\n\n win.webContents.setWindowOpenHandler(({ url }) => {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n void shell.openExternal(url);\n }\n return { action: 'deny' };\n });\n\n win.webContents.on('will-navigate', (event, url) => {\n if (process.env.ELECTRON_RENDERER_URL && url.startsWith(process.env.ELECTRON_RENDERER_URL)) {\n return;\n }\n if (url.startsWith('http://') || url.startsWith('https://')) {\n event.preventDefault();\n void shell.openExternal(url);\n }\n });\n\n const rendererLogger = getLogger('wood:main').named(`renderer:${windowId}`);\n const levelMap: Record<number, 'debug' | 'info' | 'warn' | 'error'> = {\n 0: 'debug',\n 1: 'info',\n 2: 'warn',\n 3: 'error',\n };\n\n win.webContents.on('console-message', (_event, level, message, line, sourceId) => {\n const method = levelMap[level] ?? 'info';\n rendererLogger[method](message, { source: sourceId, line, windowId });\n });\n\n if (process.env.ELECTRON_RENDERER_URL) {\n void win.loadURL(process.env.ELECTRON_RENDERER_URL);\n } else {\n void win.loadFile(rendererFile);\n }\n\n if (options.traceTransport === 'messageport' && options.rendererTraceEnabled === true) {\n const { port1, port2 } = new MessageChannelMain();\n\n const portHandler = (event: Electron.MessageEvent) => {\n dispatchRendererTracePayload(event.data, {\n windowId,\n webContentsId: win.webContents.id,\n });\n };\n port1.on('message', portHandler);\n port1.start();\n\n win.webContents.once('did-finish-load', () => {\n if (!win.isDestroyed()) {\n win.webContents.postMessage('__trace-port', null, [port2]);\n logger.info('trace messageport sent to renderer', { windowId });\n }\n });\n\n win.on('closed', () => {\n port1.off('message', portHandler);\n port1.close();\n });\n }\n\n win.on('closed', () => {\n windows.delete(windowId);\n rendererHealth.delete(windowId);\n if (windowId === 'main') {\n mainWindow = null;\n }\n if (windows.size === 0) {\n electronApp.quit();\n }\n });\n\n if (options.onWindowCreated) {\n Promise.resolve(options.onWindowCreated(windowId, win, runtimeContext!)).catch((error) => {\n runtimeLogger.warn('window created hook failed', {\n windowId,\n error: toErrorMessage(error),\n });\n });\n }\n\n logger.info('window created', { windowId });\n return win;\n };\n\n const bootstrapActivationGate = new BootstrapActivationGate(\n () => BrowserWindow.getAllWindows().length > 0,\n () => {\n createWindow('main');\n },\n );\n\n const navigateWindow = async (windowId: string, route: string): Promise<void> => {\n const win = createWindow(windowId);\n await waitForWindowReady(win);\n safeSend(windowId, win, '__event:__navigate', { route });\n win.show();\n win.focus();\n };\n\n const dispatchPushEvent = (\n channel: string,\n data: unknown,\n options?: IpcPushOptions,\n ): void => {\n const eventChannel = channel.startsWith('__event:')\n ? channel\n : `__event:${channel}`;\n\n if (options?.windowId) {\n const target = getWindow(options.windowId);\n if (target) {\n safeSend(options.windowId, target, eventChannel, data);\n }\n return;\n }\n\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n safeSend(windowId, win, eventChannel, data);\n }\n };\n\n setIpcPushSender(dispatchPushEvent);\n\n const broadcast = (channel: string, data: unknown): void => {\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n safeSend(windowId, win, channel, data);\n }\n };\n\n runtimeContext = {\n ...bootContext,\n container,\n applicationRoot: '',\n getWindow,\n createWindow,\n navigateWindow,\n broadcast,\n getRendererHealthState,\n setRendererLogCallback: (callback) => {\n getRendererLogDispatcher().setCallback(callback);\n },\n getRendererLogCallback: () => getRendererLogDispatcher().getCallback(),\n getDebugMetadata,\n // Late-bound after bootRuntime constructs the router (see bootstrap).\n dispatch: async () => {\n throw new Error('WoodMainRuntimeContext.dispatch called before the runtime router was constructed.');\n },\n };\n\n const bootstrap = async () => {\n logger.info('bootstrap starting');\n const applicationRoot = setApplicationRoot(path.join(electronApp.getPath('userData'), 'wood'));\n runtimeContext!.applicationRoot = applicationRoot;\n logger.info('application root configured', { applicationRoot });\n\n if (options.mainBoot) {\n const bootResult = await options.mainBoot(appBootResult, runtimeContext!);\n if (typeof bootResult === 'function') {\n mainBootCleanup = bootResult;\n }\n }\n\n const { router: runtimeRouter } = await bootRuntime({\n container,\n ipcMain,\n registerRuntime: options.registerRuntime,\n controllersDir: resolveRuntimePath(options.controllersDir),\n middlewareDir: resolveRuntimePath(options.middlewareDir),\n ...(options.traceMinLevel ? { traceMinLevel: options.traceMinLevel } : {}),\n ...(typeof options.rendererTraceEnabled === 'boolean'\n ? { rendererTraceEnabled: options.rendererTraceEnabled }\n : {}),\n ...(options.rendererTraceMinLevel\n ? { rendererTraceMinLevel: options.rendererTraceMinLevel }\n : {}),\n ...(options.traceTransport === 'messageport' ? { enableRendererTraceBridge: false } : {}),\n onLoad: options.onLoad ?? (async () => {\n throw new Error('Reserved channel \"__load\" is not configured for this app.');\n }),\n onNavigate: async (rawData) => {\n const data = rawData as { windowId?: string; route?: string };\n if (!data.windowId) {\n throw new Error('__navigate requires windowId');\n }\n if (!data.route) {\n throw new Error('__navigate requires route');\n }\n await navigateWindow(data.windowId, data.route);\n return { ok: true };\n },\n onWindow: async (rawData, event) => {\n const data = rawData as { action?: string; windowId?: string };\n const action = data.action ?? '';\n const windowId = data.windowId;\n\n if (action === 'current') {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const senderWindowId = ipcEvent?.sender ? findWindowIdByWebContents(ipcEvent.sender.id) : null;\n if (!senderWindowId) {\n return { ok: false };\n }\n const senderWindowDef = resolveWindowDef(options.windowDefs, senderWindowId);\n return {\n ok: true,\n windowId: senderWindowId,\n defaultRoute: senderWindowDef.defaultRoute,\n };\n }\n\n if (action === 'open') {\n if (!windowId) {\n throw new Error('__window.open requires windowId');\n }\n createWindow(windowId);\n return { ok: true };\n }\n\n const win = windowId ? getWindow(windowId) : mainWindow;\n if (!win) {\n return { ok: false };\n }\n\n switch (action) {\n case 'close':\n win.close();\n return { ok: true };\n case 'focus':\n win.show();\n win.focus();\n return { ok: true };\n case 'minimize':\n win.minimize();\n return { ok: true };\n case 'maximize':\n win.isMaximized() ? win.unmaximize() : win.maximize();\n return { ok: true };\n default:\n return { ok: false };\n }\n },\n onDebug: async (rawData) => {\n const data = rawData as { action?: string } | undefined;\n const action = data?.action ?? '';\n\n if (action === 'current') {\n return getDebugMetadata();\n }\n\n return { ok: false };\n },\n onContextMenu: options.onContextMenu ?? (async (_rawData: unknown, event?: unknown) => {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const senderId = ipcEvent?.sender?.id;\n runtimeLogger.debug('context menu requested', { senderId });\n return { ok: true };\n }),\n resolveRendererTraceContext: (event) => {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const webContentsId = ipcEvent?.sender?.id;\n if (typeof webContentsId !== 'number') {\n return undefined;\n }\n return {\n webContentsId,\n windowId: findWindowIdByWebContents(webContentsId) ?? undefined,\n };\n },\n });\n\n runtimeContext!.dispatch = (channel: string, payload?: unknown) =>\n runtimeRouter.dispatch(channel, payload ?? {});\n\n bootstrapActivationGate.ready();\n logger.info('bootstrap complete');\n };\n\n const handleBootstrapFailure = (error: unknown): void => {\n bootstrapActivationGate.failed();\n logger.error('bootstrap failed', {\n message: toErrorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n };\n void electronApp.whenReady().then(bootstrap).catch(handleBootstrapFailure);\n\n const registerApplicationLifecycle = (): void => {\n electronApp.on(\n 'browser-window-created',\n (_event: ElectronEvent, window: ElectronBrowserWindow) => {\n window.on('close', (event) => {\n const isTrackedWindow = [...windows.values()].includes(window);\n if (!isTrackedWindow\n || !shouldDeferLastWindowCloseForCleanup(\n windows.size,\n beforeQuitCleanupComplete,\n )) {\n return;\n }\n event.preventDefault();\n if (!beforeQuitCleanupPromise) {\n logger.debug('deferring last window close for renderer trace drain');\n electronApp.quit();\n }\n });\n },\n );\n\n const destroyWindowsForQuit = (): void => {\n for (const [id, win] of windows) {\n if (!win.isDestroyed()) {\n win.destroy();\n logger.debug('destroyed window on quit', { windowId: id });\n }\n }\n windows.clear();\n };\n\n const runBeforeQuitCleanup = async (): Promise<void> => {\n await drainRendererTracesBeforeQuit(\n rendererTraceDrain,\n windows.values(),\n logger,\n Date.now() + 1_000,\n );\n clearIpcPushSender();\n if (mainBootCleanup) {\n await mainBootCleanup();\n }\n if (options.onBeforeQuit) {\n await options.onBeforeQuit(runtimeContext!);\n }\n };\n\n electronApp.on('before-quit', (event: ElectronEvent) => {\n if (!runtimeContext) {\n return;\n }\n\n if (beforeQuitCleanupComplete) {\n destroyWindowsForQuit();\n return;\n }\n\n event.preventDefault();\n if (beforeQuitCleanupPromise) {\n return;\n }\n\n beforeQuitCleanupPromise = (async () => {\n try {\n await runBeforeQuitCleanup();\n } catch (error) {\n logger.warn('before-quit handler failed', { error: toErrorMessage(error) });\n } finally {\n beforeQuitCleanupComplete = true;\n beforeQuitCleanupPromise = null;\n }\n\n destroyWindowsForQuit();\n electronApp.quit();\n })();\n });\n\n electronApp.on('window-all-closed', () => {\n electronApp.quit();\n });\n\n electronApp.on('activate', () => {\n bootstrapActivationGate.activate();\n });\n };\n\n registerApplicationLifecycle();\n };\n\n void initializeRuntime().catch((error) => {\n rendererTraceDrain.stop();\n logger.error('startup failed before ready', {\n message: toErrorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n });\n}\n"],"mappings":"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","names":["options"]}
1
+ {"version":3,"sources":["../../src/main/index.ts"],"sourcesContent":["import path from 'path';\nimport {\n app as electronApp,\n BrowserWindow,\n ipcMain,\n MessageChannelMain,\n Menu,\n protocol,\n net,\n shell,\n screen,\n} from 'electron';\nimport type {\n BrowserWindowConstructorOptions,\n BrowserWindow as ElectronBrowserWindow,\n Event as ElectronEvent,\n IpcMainInvokeEvent,\n Privileges,\n RenderProcessGoneDetails,\n} from 'electron';\nimport { getLogger } from '@noego/logger';\nimport { WindowStateStore } from '../window/window_state_store.js';\nimport { getContainer } from '../runtime/get_container.js';\nimport { runtime as bootRuntime } from '../runtime/runtime.js';\nimport { dispatchRendererTracePayload, type TraceLevel } from '../tracing/index.js';\nimport { setApplicationRoot } from '../runtime/application_root.js';\nimport type { RegisterRuntimeRouter } from '../runtime/runtime.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogCallback,\n} from '../runtime/renderer_log_dispatcher.js';\nimport {\n setRendererLogRecordFilter,\n type RendererLogRecordFilter,\n} from '../runtime/renderer_log_batch_receiver.js';\nexport {\n setRendererLogRecordFilter,\n type RendererLogRecordFilter,\n} from '../runtime/renderer_log_batch_receiver.js';\nimport {\n setRendererConfigExtension,\n type RendererConfigExtension,\n} from '../runtime/renderer_config_extension.js';\nexport {\n setRendererConfigExtension,\n type RendererConfigExtension,\n} from '../runtime/renderer_config_extension.js';\nimport { Ipc, getIpc } from '../ipc/index.js';\nimport { setIpcPushSender, clearIpcPushSender, type IpcPushOptions } from '../ipc/shared.js';\nimport {\n drainRendererTracesBeforeQuit,\n RendererTraceDrainCoordinator,\n} from './renderer_trace_drain_coordinator.js';\n\ntype CleanupHandler = () => void | Promise<void>;\n\nexport type BootstrapActivationState = 'pending' | 'ready' | 'failed';\n\n/**\n * Owns the startup/activation boundary so Electron activation cannot create a\n * renderer until bootstrap has registered the runtime IPC handlers.\n */\nexport class BootstrapActivationGate {\n private currentState: BootstrapActivationState = 'pending';\n\n constructor(\n private readonly hasWindow: () => boolean,\n private readonly createMainWindow: () => void,\n ) {}\n\n get state(): BootstrapActivationState {\n return this.currentState;\n }\n\n activate(): void {\n if (this.currentState === 'ready' && !this.hasWindow()) {\n this.createMainWindow();\n }\n }\n\n ready(): void {\n if (this.currentState !== 'pending') {\n return;\n }\n\n // createMainWindow may throw. Leave the gate pending so the bootstrap\n // rejection can make the failure terminal rather than exposing readiness.\n this.createMainWindow();\n this.currentState = 'ready';\n }\n\n failed(): void {\n if (this.currentState === 'pending') {\n this.currentState = 'failed';\n }\n }\n}\n\nexport type RendererHealthState =\n | 'ready'\n | 'loading'\n | 'unresponsive'\n | 'gone'\n | 'destroyed';\n\nexport type WoodWindowConfig = {\n title: string;\n width: number;\n height: number;\n defaultRoute?: string;\n frame?: boolean;\n transparent?: boolean;\n resizable?: boolean;\n alwaysOnTop?: boolean;\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n show?: boolean;\n parent?: string;\n modal?: boolean;\n vibrancy?: string;\n backgroundMaterial?: string;\n backgroundColor?: string;\n rememberBounds?: boolean;\n contextMenu?: 'native' | 'custom';\n acceptFirstMouse?: boolean;\n nativeQuitFallback?: boolean;\n titleBarStyle?: 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover';\n trafficLightPosition?: { x: number; y: number };\n titleBarOverlay?: boolean | { color?: string; symbolColor?: string; height?: number };\n};\n\nexport type PrivilegedSchemeRegistration = {\n scheme: string;\n privileges: Privileges;\n};\n\nexport interface WoodMainAppBootResult {\n scope?: string;\n configureContainer?: (container: any) => void;\n registerSchemesAsPrivileged?: PrivilegedSchemeRegistration[];\n}\n\nexport interface WoodMainBootContext {\n electron: {\n app: typeof electronApp;\n BrowserWindow: typeof BrowserWindow;\n ipcMain: typeof ipcMain;\n protocol: typeof protocol;\n net: typeof net;\n shell: typeof shell;\n screen: typeof screen;\n Menu: typeof Menu;\n };\n logger: ReturnType<typeof getLogger>;\n}\n\nexport function shouldDeferLastWindowCloseForCleanup(\n trackedWindowCount: number,\n cleanupComplete: boolean,\n): boolean {\n return trackedWindowCount === 1 && !cleanupComplete;\n}\n\nexport interface WoodMainRuntimeContext extends WoodMainBootContext {\n container: any;\n applicationRoot: string;\n getWindow: (windowId: string) => ElectronBrowserWindow | null;\n createWindow: (windowId?: string) => ElectronBrowserWindow;\n navigateWindow: (windowId: string, route: string) => Promise<void>;\n broadcast: (channel: string, data: unknown) => void;\n /**\n * Dispatch a channel through the SAME real WoodRouter the ipcMain handlers\n * wrap — full operations-YAML schema validation, controllers, middleware.\n * Available only after the runtime finishes booting (mainBoot runs before the\n * router is constructed, so callers must invoke this lazily, not during\n * mainBoot). This is the in-main seam the launch-flag-gated test control plane\n * uses for driver `api.call`; production code never calls it.\n */\n dispatch: (channel: string, payload?: unknown) => Promise<unknown>;\n getRendererHealthState: (windowId: string) => RendererHealthState | null;\n setRendererLogCallback: (callback: RendererLogCallback | null) => void;\n getRendererLogCallback: () => RendererLogCallback | null;\n /** Filters renderer log records received via the batched __log_batch channel. */\n setRendererLogRecordFilter: (filter: RendererLogRecordFilter | null) => void;\n /**\n * Adds app fields to the `__woodConfig` payload renderers fetch at boot\n * (e.g. an external log sink's port + per-boot token). Wood's own keys win.\n */\n setRendererConfigExtension: (extension: RendererConfigExtension | null) => void;\n getDebugMetadata: () => WoodDebugMetadata;\n}\n\nexport interface WoodRendererHealthEvent {\n windowId: string;\n state: RendererHealthState;\n previousState: RendererHealthState | null;\n webContentsId?: number;\n reason?: string;\n exitCode?: number;\n}\n\nexport type WoodWindowLifecycleContext = WoodMainRuntimeContext;\n\nexport interface StartWoodMainOptions {\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n windowDefs: Record<string, WoodWindowConfig>;\n controllersDir: string;\n middlewareDir: string;\n outDir?: string;\n scope?: string;\n configureContainer?: (container: any) => void;\n appBoot?: (\n context: WoodMainBootContext,\n ) => void | WoodMainAppBootResult | Promise<void | WoodMainAppBootResult>;\n mainBoot?: (\n appBootResult: unknown,\n context: WoodMainRuntimeContext,\n ) => void | CleanupHandler | Promise<void | CleanupHandler>;\n onBeforeQuit?: (context: WoodMainRuntimeContext) => void | Promise<void>;\n onWindowCreated?: (\n windowId: string,\n win: ElectronBrowserWindow,\n context: WoodMainRuntimeContext,\n ) => void | Promise<void>;\n onRendererHealthChanged?: (\n event: WoodRendererHealthEvent,\n context: WoodMainRuntimeContext,\n ) => void | Promise<void>;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n traceTransport?: 'ipc' | 'messageport';\n}\n\nexport interface WoodDebugWindowMetadata {\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: RendererHealthState;\n}\n\nexport interface WoodDebugMetadata {\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: WoodDebugWindowMetadata[];\n}\n\nconst DEFAULT_WOOD_REMOTE_DEBUGGING_PORT = 9333;\n\nexport function resolveWoodDebugMetadataConfiguration(env: NodeJS.ProcessEnv = process.env): {\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n} {\n const isDevelopment = env.WOOD_MODE === 'development';\n if (!isDevelopment) {\n return {\n enabled: false,\n mode: 'production',\n };\n }\n\n const rawPort = env.WOOD_REMOTE_DEBUGGING_PORT;\n const parsedPort = rawPort ? Number.parseInt(rawPort, 10) : DEFAULT_WOOD_REMOTE_DEBUGGING_PORT;\n const port = Number.isFinite(parsedPort) && parsedPort > 0\n ? parsedPort\n : DEFAULT_WOOD_REMOTE_DEBUGGING_PORT;\n\n return {\n enabled: true,\n mode: 'development',\n port,\n };\n}\n\nfunction resolveWindowDef(\n windowDefs: Record<string, WoodWindowConfig>,\n windowId = 'main',\n): WoodWindowConfig {\n const def = windowDefs[windowId];\n if (!def) {\n throw new Error(`Window \"${windowId}\" not defined in generated window defs.`);\n }\n return def;\n}\n\nfunction resolveRuntimePath(relativeOrAbsolutePath: string): string {\n if (path.isAbsolute(relativeOrAbsolutePath)) {\n return relativeOrAbsolutePath;\n }\n return path.join(electronApp.getAppPath(), relativeOrAbsolutePath);\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function startWoodMain(options: StartWoodMainOptions): void {\n const logger = getLogger('wood:main').named('bootstrap');\n const runtimeLogger = getLogger('wood:main').named('runtime');\n const debugConfig = resolveWoodDebugMetadataConfiguration();\n const windowState = new WindowStateStore();\n const windows = new Map<string, ElectronBrowserWindow>();\n const rendererHealth = new Map<string, RendererHealthState>();\n let mainWindow: ElectronBrowserWindow | null = null;\n let beforeQuitCleanupComplete = false;\n let beforeQuitCleanupPromise: Promise<void> | null = null;\n let runtimeContext: WoodMainRuntimeContext | null = null;\n let mainBootCleanup: CleanupHandler | undefined;\n let nativeQuitFallbackInstalled = false;\n const rendererTraceDrain = new RendererTraceDrainCoordinator(ipcMain);\n rendererTraceDrain.start();\n\n for (const stream of [process.stdout, process.stderr]) {\n stream.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') {\n return;\n }\n throw error;\n });\n }\n\n if (debugConfig.enabled && debugConfig.port) {\n electronApp.commandLine.appendSwitch('remote-debugging-port', String(debugConfig.port));\n electronApp.commandLine.appendSwitch('remote-debugging-address', '127.0.0.1');\n logger.info('devtools remote debugging enabled', {\n port: debugConfig.port,\n mode: debugConfig.mode,\n });\n }\n\n const bootContext: WoodMainBootContext = {\n electron: {\n app: electronApp,\n BrowserWindow,\n ipcMain,\n protocol,\n net,\n shell,\n screen,\n Menu,\n },\n logger,\n };\n\n const initializeRuntime = async (): Promise<void> => {\n const appBootResult = options.appBoot\n ? await options.appBoot(bootContext)\n : undefined;\n\n const bootOverrides = (appBootResult ?? {}) as WoodMainAppBootResult;\n const scope = bootOverrides.scope ?? options.scope ?? process.cwd();\n const configureContainer = bootOverrides.configureContainer ?? options.configureContainer;\n const privilegedSchemes = Array.isArray(bootOverrides.registerSchemesAsPrivileged)\n ? bootOverrides.registerSchemesAsPrivileged\n : [];\n\n if (privilegedSchemes.length > 0) {\n protocol.registerSchemesAsPrivileged(privilegedSchemes);\n logger.info('registered privileged schemes', {\n count: privilegedSchemes.length,\n schemes: privilegedSchemes.map((entry) => entry.scheme),\n });\n }\n\n const outDir = options.outDir ?? 'out';\n const preloadPath = path.join(electronApp.getAppPath(), outDir, 'preload', 'index.js');\n const rendererFile = path.join(electronApp.getAppPath(), outDir, 'renderer', 'index.html');\n\n const container = getContainer({\n scope,\n ...(configureContainer ? { configure: configureContainer } : {}),\n });\n\n const registrationContainer = container as {\n registerFunction?: (\n token: any,\n resolver: (...args: any[]) => unknown,\n options?: Record<string, unknown>,\n ) => void;\n };\n\n if (typeof registrationContainer.registerFunction === 'function') {\n registrationContainer.registerFunction(Ipc, () => getIpc());\n }\n\n const getWindow = (windowId: string): ElectronBrowserWindow | null => {\n const existing = windows.get(windowId);\n if (!existing) {\n return null;\n }\n if (existing.isDestroyed()) {\n windows.delete(windowId);\n return null;\n }\n return existing;\n };\n\n const findWindowIdByWebContents = (webContentsId: number): string | null => {\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n if (win.webContents.id === webContentsId) {\n return windowId;\n }\n }\n return null;\n };\n\n const getRendererHealthState = (windowId: string): RendererHealthState | null => {\n return rendererHealth.get(windowId) ?? null;\n };\n\n const notifyRendererHealthChanged = (event: WoodRendererHealthEvent): void => {\n if (!options.onRendererHealthChanged) {\n return;\n }\n if (!runtimeContext) {\n runtimeLogger.warn('renderer health hook skipped before runtime context', {\n windowId: event.windowId,\n state: event.state,\n });\n return;\n }\n\n Promise.resolve(options.onRendererHealthChanged(event, runtimeContext)).catch((error) => {\n runtimeLogger.warn('renderer health hook failed', {\n windowId: event.windowId,\n state: event.state,\n error: toErrorMessage(error),\n });\n });\n };\n\n const setRendererHealth = (\n windowId: string,\n state: RendererHealthState,\n details: {\n webContentsId?: number;\n reason?: string;\n exitCode?: number;\n } = {},\n ): void => {\n const previousState = rendererHealth.get(windowId) ?? null;\n rendererHealth.set(windowId, state);\n notifyRendererHealthChanged({\n windowId,\n state,\n previousState,\n ...details,\n });\n };\n\n const attachRendererHealth = (windowId: string, win: ElectronBrowserWindow): void => {\n const healthLogger = getLogger('wood:main').named(`renderer-health:${windowId}`);\n const webContentsId = win.webContents.id;\n\n setRendererHealth(windowId, 'loading', { webContentsId });\n\n win.webContents.on('did-start-loading', () => {\n setRendererHealth(windowId, 'loading', { webContentsId });\n healthLogger.info('renderer loading', { windowId, webContentsId });\n });\n\n win.webContents.on('did-finish-load', () => {\n setRendererHealth(windowId, 'ready', { webContentsId });\n healthLogger.info('renderer ready', { windowId, webContentsId });\n });\n\n win.webContents.on('unresponsive', () => {\n setRendererHealth(windowId, 'unresponsive', { webContentsId });\n healthLogger.error('renderer unresponsive', { windowId, webContentsId });\n });\n\n win.webContents.on('responsive', () => {\n setRendererHealth(windowId, 'ready', { webContentsId });\n healthLogger.info('renderer responsive', { windowId, webContentsId });\n });\n\n win.webContents.on('render-process-gone', (_event, details: RenderProcessGoneDetails) => {\n setRendererHealth(windowId, 'gone', {\n webContentsId,\n reason: details.reason,\n exitCode: details.exitCode,\n });\n healthLogger.error('renderer process gone', {\n windowId,\n webContentsId,\n reason: details.reason,\n exitCode: details.exitCode,\n });\n });\n\n win.webContents.on('destroyed', () => {\n setRendererHealth(windowId, 'destroyed');\n healthLogger.warn('renderer destroyed', { windowId, webContentsId });\n });\n\n win.on('closed', () => {\n setRendererHealth(windowId, 'destroyed');\n rendererHealth.delete(windowId);\n });\n };\n\n const canSendToWindow = (win: ElectronBrowserWindow): boolean => {\n if (win.isDestroyed()) {\n return false;\n }\n if (win.webContents.isDestroyed()) {\n return false;\n }\n if (typeof win.webContents.isCrashed === 'function' && win.webContents.isCrashed()) {\n return false;\n }\n return true;\n };\n\n const safeSend = (\n windowId: string,\n win: ElectronBrowserWindow,\n channel: string,\n data: unknown,\n ): boolean => {\n if (!canSendToWindow(win)) {\n runtimeLogger.warn('skipping send to unhealthy renderer', {\n windowId,\n channel,\n rendererHealth: getRendererHealthState(windowId),\n });\n return false;\n }\n\n try {\n win.webContents.send(channel, data);\n return true;\n } catch (error) {\n runtimeLogger.warn('send to renderer failed', {\n windowId,\n channel,\n rendererHealth: getRendererHealthState(windowId),\n error: toErrorMessage(error),\n });\n return false;\n }\n };\n\n const installNativeQuitFallback = (): void => {\n if (nativeQuitFallbackInstalled) {\n return;\n }\n Menu.setApplicationMenu(Menu.buildFromTemplate([\n {\n label: electronApp.name,\n submenu: [\n { role: 'quit' },\n ],\n },\n ]));\n nativeQuitFallbackInstalled = true;\n logger.info('native quit fallback installed');\n };\n\n const waitForWindowReady = async (win: ElectronBrowserWindow): Promise<void> => {\n const webContents = win.webContents as ElectronBrowserWindow['webContents'] & {\n isLoadingMainFrame?: () => boolean;\n };\n const isLoading = typeof webContents.isLoadingMainFrame === 'function'\n ? webContents.isLoadingMainFrame()\n : webContents.isLoading();\n if (!isLoading) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n webContents.once('did-finish-load', () => resolve());\n });\n };\n\n const getDebugMetadata = (): WoodDebugMetadata => {\n const debugWindows: WoodDebugWindowMetadata[] = [];\n\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n\n debugWindows.push({\n windowId,\n title: win.getTitle(),\n webContentsId: win.webContents.id,\n url: win.webContents.getURL(),\n focused: win.isFocused(),\n rendererHealth: getRendererHealthState(windowId) ?? undefined,\n });\n }\n\n return {\n ok: true,\n enabled: debugConfig.enabled,\n mode: debugConfig.mode,\n ...(debugConfig.port ? { port: debugConfig.port } : {}),\n windows: debugWindows,\n };\n };\n\n const createWindow = (windowId = 'main'): ElectronBrowserWindow => {\n const existing = getWindow(windowId);\n if (existing) {\n existing.show();\n existing.focus();\n return existing;\n }\n\n const windowDef = resolveWindowDef(options.windowDefs, windowId);\n const defaultShow = windowDef.show ?? true;\n const parentWindow = windowDef.parent ? getWindow(windowDef.parent) : null;\n\n if (windowDef.nativeQuitFallback === true) {\n installNativeQuitFallback();\n }\n\n windowState.setScreen(screen);\n const savedBounds = windowDef.rememberBounds ? windowState.getBounds(windowId) : null;\n\n const windowOptions: BrowserWindowConstructorOptions = {\n width: savedBounds?.width ?? windowDef.width,\n height: savedBounds?.height ?? windowDef.height,\n ...(savedBounds ? { x: savedBounds.x, y: savedBounds.y } : {}),\n ...(windowDef.minWidth != null ? { minWidth: windowDef.minWidth } : {}),\n ...(windowDef.minHeight != null ? { minHeight: windowDef.minHeight } : {}),\n ...(windowDef.maxWidth != null ? { maxWidth: windowDef.maxWidth } : {}),\n ...(windowDef.maxHeight != null ? { maxHeight: windowDef.maxHeight } : {}),\n ...(typeof windowDef.modal === 'boolean' ? { modal: windowDef.modal } : {}),\n ...(parentWindow ? { parent: parentWindow } : {}),\n title: windowDef.title,\n frame: windowDef.frame ?? true,\n transparent: windowDef.transparent ?? false,\n resizable: windowDef.resizable ?? true,\n alwaysOnTop: windowDef.alwaysOnTop ?? false,\n ...(typeof windowDef.backgroundColor === 'string' ? { backgroundColor: windowDef.backgroundColor } : {}),\n ...(process.platform === 'darwin' && typeof windowDef.vibrancy === 'string'\n ? {\n vibrancy: windowDef.vibrancy as BrowserWindowConstructorOptions['vibrancy'],\n visualEffectState: 'active' as const,\n }\n : {}),\n ...(process.platform === 'win32' && typeof windowDef.backgroundMaterial === 'string'\n ? {\n backgroundMaterial: windowDef.backgroundMaterial as BrowserWindowConstructorOptions['backgroundMaterial'],\n }\n : {}),\n ...(typeof windowDef.acceptFirstMouse === 'boolean' ? { acceptFirstMouse: windowDef.acceptFirstMouse } : {}),\n // Hidden title bar with native window controls: macOS draws the\n // traffic lights (positionable), Windows draws min/max/close via the\n // Window Controls Overlay (always top-right; styled via titleBarOverlay).\n ...(typeof windowDef.titleBarStyle === 'string'\n ? { titleBarStyle: windowDef.titleBarStyle as BrowserWindowConstructorOptions['titleBarStyle'] }\n : {}),\n ...(process.platform === 'darwin' && windowDef.trafficLightPosition\n ? { trafficLightPosition: windowDef.trafficLightPosition }\n : {}),\n ...(process.platform === 'win32' && windowDef.titleBarOverlay != null\n ? { titleBarOverlay: windowDef.titleBarOverlay }\n : {}),\n show: savedBounds ? false : defaultShow,\n webPreferences: {\n preload: preloadPath,\n contextIsolation: true,\n nodeIntegration: false,\n },\n };\n\n const win = new BrowserWindow(windowOptions);\n windows.set(windowId, win);\n attachRendererHealth(windowId, win);\n if (windowId === 'main') {\n mainWindow = win;\n }\n\n if (savedBounds?.isMaximized) {\n win.maximize();\n } else if (savedBounds?.isFullScreen) {\n win.setFullScreen(true);\n }\n\n if (savedBounds && defaultShow) {\n win.show();\n }\n\n if (windowDef.rememberBounds) {\n const captureNormalBounds = () => {\n if (!win.isMaximized() && !win.isFullScreen()) {\n const rect = win.getBounds();\n windowState.updateBoundsDebounced(windowId, {\n ...rect,\n isMaximized: false,\n isFullScreen: false,\n });\n }\n };\n win.on('move', captureNormalBounds);\n win.on('resize', captureNormalBounds);\n win.on('close', () => {\n const rect = win.getBounds();\n windowState.saveBoundsSync(windowId, {\n ...rect,\n isMaximized: win.isMaximized(),\n isFullScreen: win.isFullScreen(),\n });\n });\n }\n\n win.webContents.setWindowOpenHandler(({ url }) => {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n void shell.openExternal(url);\n }\n return { action: 'deny' };\n });\n\n win.webContents.on('will-navigate', (event, url) => {\n if (process.env.ELECTRON_RENDERER_URL && url.startsWith(process.env.ELECTRON_RENDERER_URL)) {\n return;\n }\n if (url.startsWith('http://') || url.startsWith('https://')) {\n event.preventDefault();\n void shell.openExternal(url);\n }\n });\n\n const rendererLogger = getLogger('wood:main').named(`renderer:${windowId}`);\n const levelMap: Record<number, 'debug' | 'info' | 'warn' | 'error'> = {\n 0: 'debug',\n 1: 'info',\n 2: 'warn',\n 3: 'error',\n };\n\n win.webContents.on('console-message', (_event, level, message, line, sourceId) => {\n const method = levelMap[level] ?? 'info';\n rendererLogger[method](message, { source: sourceId, line, windowId });\n });\n\n if (process.env.ELECTRON_RENDERER_URL) {\n void win.loadURL(process.env.ELECTRON_RENDERER_URL);\n } else {\n void win.loadFile(rendererFile);\n }\n\n if (options.traceTransport === 'messageport' && options.rendererTraceEnabled === true) {\n const { port1, port2 } = new MessageChannelMain();\n\n const portHandler = (event: Electron.MessageEvent) => {\n dispatchRendererTracePayload(event.data, {\n windowId,\n webContentsId: win.webContents.id,\n });\n };\n port1.on('message', portHandler);\n port1.start();\n\n win.webContents.once('did-finish-load', () => {\n if (!win.isDestroyed()) {\n win.webContents.postMessage('__trace-port', null, [port2]);\n logger.info('trace messageport sent to renderer', { windowId });\n }\n });\n\n win.on('closed', () => {\n port1.off('message', portHandler);\n port1.close();\n });\n }\n\n win.on('closed', () => {\n windows.delete(windowId);\n rendererHealth.delete(windowId);\n if (windowId === 'main') {\n mainWindow = null;\n }\n if (windows.size === 0) {\n electronApp.quit();\n }\n });\n\n if (options.onWindowCreated) {\n Promise.resolve(options.onWindowCreated(windowId, win, runtimeContext!)).catch((error) => {\n runtimeLogger.warn('window created hook failed', {\n windowId,\n error: toErrorMessage(error),\n });\n });\n }\n\n logger.info('window created', { windowId });\n return win;\n };\n\n const bootstrapActivationGate = new BootstrapActivationGate(\n () => BrowserWindow.getAllWindows().length > 0,\n () => {\n createWindow('main');\n },\n );\n\n const navigateWindow = async (windowId: string, route: string): Promise<void> => {\n const win = createWindow(windowId);\n await waitForWindowReady(win);\n safeSend(windowId, win, '__event:__navigate', { route });\n win.show();\n win.focus();\n };\n\n const dispatchPushEvent = (\n channel: string,\n data: unknown,\n options?: IpcPushOptions,\n ): void => {\n const eventChannel = channel.startsWith('__event:')\n ? channel\n : `__event:${channel}`;\n\n if (options?.windowId) {\n const target = getWindow(options.windowId);\n if (target) {\n safeSend(options.windowId, target, eventChannel, data);\n }\n return;\n }\n\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n safeSend(windowId, win, eventChannel, data);\n }\n };\n\n setIpcPushSender(dispatchPushEvent);\n\n const broadcast = (channel: string, data: unknown): void => {\n for (const [windowId, win] of windows.entries()) {\n if (win.isDestroyed()) {\n windows.delete(windowId);\n continue;\n }\n safeSend(windowId, win, channel, data);\n }\n };\n\n runtimeContext = {\n ...bootContext,\n container,\n applicationRoot: '',\n getWindow,\n createWindow,\n navigateWindow,\n broadcast,\n getRendererHealthState,\n setRendererLogCallback: (callback) => {\n getRendererLogDispatcher().setCallback(callback);\n },\n getRendererLogCallback: () => getRendererLogDispatcher().getCallback(),\n setRendererLogRecordFilter,\n setRendererConfigExtension,\n getDebugMetadata,\n // Late-bound after bootRuntime constructs the router (see bootstrap).\n dispatch: async () => {\n throw new Error('WoodMainRuntimeContext.dispatch called before the runtime router was constructed.');\n },\n };\n\n const bootstrap = async () => {\n logger.info('bootstrap starting');\n const applicationRoot = setApplicationRoot(path.join(electronApp.getPath('userData'), 'wood'));\n runtimeContext!.applicationRoot = applicationRoot;\n logger.info('application root configured', { applicationRoot });\n\n if (options.mainBoot) {\n const bootResult = await options.mainBoot(appBootResult, runtimeContext!);\n if (typeof bootResult === 'function') {\n mainBootCleanup = bootResult;\n }\n }\n\n const { router: runtimeRouter } = await bootRuntime({\n container,\n ipcMain,\n registerRuntime: options.registerRuntime,\n controllersDir: resolveRuntimePath(options.controllersDir),\n middlewareDir: resolveRuntimePath(options.middlewareDir),\n ...(options.traceMinLevel ? { traceMinLevel: options.traceMinLevel } : {}),\n ...(typeof options.rendererTraceEnabled === 'boolean'\n ? { rendererTraceEnabled: options.rendererTraceEnabled }\n : {}),\n ...(options.rendererTraceMinLevel\n ? { rendererTraceMinLevel: options.rendererTraceMinLevel }\n : {}),\n ...(options.traceTransport === 'messageport' ? { enableRendererTraceBridge: false } : {}),\n onLoad: options.onLoad ?? (async () => {\n throw new Error('Reserved channel \"__load\" is not configured for this app.');\n }),\n onNavigate: async (rawData) => {\n const data = rawData as { windowId?: string; route?: string };\n if (!data.windowId) {\n throw new Error('__navigate requires windowId');\n }\n if (!data.route) {\n throw new Error('__navigate requires route');\n }\n await navigateWindow(data.windowId, data.route);\n return { ok: true };\n },\n onWindow: async (rawData, event) => {\n const data = rawData as { action?: string; windowId?: string };\n const action = data.action ?? '';\n const windowId = data.windowId;\n\n if (action === 'current') {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const senderWindowId = ipcEvent?.sender ? findWindowIdByWebContents(ipcEvent.sender.id) : null;\n if (!senderWindowId) {\n return { ok: false };\n }\n const senderWindowDef = resolveWindowDef(options.windowDefs, senderWindowId);\n return {\n ok: true,\n windowId: senderWindowId,\n defaultRoute: senderWindowDef.defaultRoute,\n };\n }\n\n if (action === 'open') {\n if (!windowId) {\n throw new Error('__window.open requires windowId');\n }\n createWindow(windowId);\n return { ok: true };\n }\n\n const win = windowId ? getWindow(windowId) : mainWindow;\n if (!win) {\n return { ok: false };\n }\n\n switch (action) {\n case 'close':\n win.close();\n return { ok: true };\n case 'focus':\n win.show();\n win.focus();\n return { ok: true };\n case 'minimize':\n win.minimize();\n return { ok: true };\n case 'maximize':\n win.isMaximized() ? win.unmaximize() : win.maximize();\n return { ok: true };\n default:\n return { ok: false };\n }\n },\n onDebug: async (rawData) => {\n const data = rawData as { action?: string } | undefined;\n const action = data?.action ?? '';\n\n if (action === 'current') {\n return getDebugMetadata();\n }\n\n return { ok: false };\n },\n onContextMenu: options.onContextMenu ?? (async (_rawData: unknown, event?: unknown) => {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const senderId = ipcEvent?.sender?.id;\n runtimeLogger.debug('context menu requested', { senderId });\n return { ok: true };\n }),\n resolveRendererTraceContext: (event) => {\n const ipcEvent = event as IpcMainInvokeEvent | undefined;\n const webContentsId = ipcEvent?.sender?.id;\n if (typeof webContentsId !== 'number') {\n return undefined;\n }\n return {\n webContentsId,\n windowId: findWindowIdByWebContents(webContentsId) ?? undefined,\n };\n },\n });\n\n runtimeContext!.dispatch = (channel: string, payload?: unknown) =>\n runtimeRouter.dispatch(channel, payload ?? {});\n\n bootstrapActivationGate.ready();\n logger.info('bootstrap complete');\n };\n\n const handleBootstrapFailure = (error: unknown): void => {\n bootstrapActivationGate.failed();\n logger.error('bootstrap failed', {\n message: toErrorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n };\n void electronApp.whenReady().then(bootstrap).catch(handleBootstrapFailure);\n\n const registerApplicationLifecycle = (): void => {\n electronApp.on(\n 'browser-window-created',\n (_event: ElectronEvent, window: ElectronBrowserWindow) => {\n window.on('close', (event) => {\n const isTrackedWindow = [...windows.values()].includes(window);\n if (!isTrackedWindow\n || !shouldDeferLastWindowCloseForCleanup(\n windows.size,\n beforeQuitCleanupComplete,\n )) {\n return;\n }\n event.preventDefault();\n if (!beforeQuitCleanupPromise) {\n logger.debug('deferring last window close for renderer trace drain');\n electronApp.quit();\n }\n });\n },\n );\n\n const destroyWindowsForQuit = (): void => {\n for (const [id, win] of windows) {\n if (!win.isDestroyed()) {\n win.destroy();\n logger.debug('destroyed window on quit', { windowId: id });\n }\n }\n windows.clear();\n };\n\n const runBeforeQuitCleanup = async (): Promise<void> => {\n await drainRendererTracesBeforeQuit(\n rendererTraceDrain,\n windows.values(),\n logger,\n Date.now() + 1_000,\n );\n clearIpcPushSender();\n if (mainBootCleanup) {\n await mainBootCleanup();\n }\n if (options.onBeforeQuit) {\n await options.onBeforeQuit(runtimeContext!);\n }\n };\n\n electronApp.on('before-quit', (event: ElectronEvent) => {\n if (!runtimeContext) {\n return;\n }\n\n if (beforeQuitCleanupComplete) {\n destroyWindowsForQuit();\n return;\n }\n\n event.preventDefault();\n if (beforeQuitCleanupPromise) {\n return;\n }\n\n beforeQuitCleanupPromise = (async () => {\n try {\n await runBeforeQuitCleanup();\n } catch (error) {\n logger.warn('before-quit handler failed', { error: toErrorMessage(error) });\n } finally {\n beforeQuitCleanupComplete = true;\n beforeQuitCleanupPromise = null;\n }\n\n destroyWindowsForQuit();\n electronApp.quit();\n })();\n });\n\n electronApp.on('window-all-closed', () => {\n electronApp.quit();\n });\n\n electronApp.on('activate', () => {\n bootstrapActivationGate.activate();\n });\n };\n\n registerApplicationLifecycle();\n };\n\n void initializeRuntime().catch((error) => {\n rendererTraceDrain.stop();\n logger.error('startup failed before ready', {\n message: toErrorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n });\n}\n"],"mappings":"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","names":["setRendererLogRecordFilter","setRendererConfigExtension","options"]}
@@ -39,17 +39,38 @@ function toImportSpecifier(spec) {
39
39
  class MiddlewareResolver {
40
40
  constructor(middlewareDir) {
41
41
  this.cache = /* @__PURE__ */ new Map();
42
+ this.registered = /* @__PURE__ */ new Map();
42
43
  this.baseDir = middlewareDir;
43
44
  }
45
+ /**
46
+ * Pre-register the executable satisfying a production middleware identity.
47
+ * Mirrors controller pre-registration: bundled builds register generated
48
+ * bindings instead of importing from the filesystem, and test environments
49
+ * replace an identity's executable while production topology (membership,
50
+ * order, inheritance) still comes from source. Last registration wins.
51
+ */
52
+ register(spec, fn) {
53
+ if (typeof fn !== "function") {
54
+ throw new Error(`registerMiddleware("${spec}"): expected a function, got ${typeof fn}`);
55
+ }
56
+ this.registered.set(spec, fn);
57
+ }
58
+ /** Whether an identity has a registered executable. */
59
+ has(spec) {
60
+ return this.registered.has(spec);
61
+ }
44
62
  /**
45
63
  * Resolve a middleware spec like "auth.admin:is_admin" into a function.
46
64
  *
47
- * Format: "file.path:function_selector"
65
+ * Registered executables win; otherwise the spec resolves from the
66
+ * filesystem. Format: "file.path:function_selector"
48
67
  * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts
49
68
  * - function_selector: named export, "*" for all, comma-separated for multiple
50
69
  * - If no colon, use default export
51
70
  */
52
71
  async resolve(spec) {
72
+ const registered = this.registered.get(spec);
73
+ if (registered) return registered;
53
74
  const cached = this.cache.get(spec);
54
75
  if (cached) return cached;
55
76
  const [filePart, selectorPart] = spec.includes(":") ? spec.split(":", 2) : [spec, "default"];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/middleware/middleware_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport type { WoodMiddlewareFn } from '../types/index.cjs';\n\n// Node's ESM loader rejects raw absolute Windows paths (`C:\\...`) — they must\n// be file:// URLs. Bare specifiers and relative paths pass through unchanged.\nfunction toImportSpecifier(spec: string): string {\n return path.isAbsolute(spec) ? pathToFileURL(spec).href : spec;\n}\n\nexport class MiddlewareResolver {\n private baseDir: string;\n private cache = new Map<string, WoodMiddlewareFn>();\n\n constructor(middlewareDir: string) {\n this.baseDir = middlewareDir;\n }\n\n /**\n * Resolve a middleware spec like \"auth.admin:is_admin\" into a function.\n *\n * Format: \"file.path:function_selector\"\n * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts\n * - function_selector: named export, \"*\" for all, comma-separated for multiple\n * - If no colon, use default export\n */\n async resolve(spec: string): Promise<WoodMiddlewareFn> {\n const cached = this.cache.get(spec);\n if (cached) return cached;\n\n const [filePart, selectorPart] = spec.includes(':')\n ? spec.split(':', 2) as [string, string]\n : [spec, 'default'];\n\n const relPath = filePart.replace(/\\./g, path.sep);\n const fullPath = path.resolve(this.baseDir, relPath);\n\n const mod = await import(toImportSpecifier(fullPath));\n\n let fn: WoodMiddlewareFn;\n if (selectorPart === 'default') {\n fn = mod.default;\n } else if (selectorPart === '*') {\n const fns = Object.values(mod).filter(v => typeof v === 'function') as WoodMiddlewareFn[];\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else if (selectorPart.includes(',')) {\n const names = selectorPart.split(',').map(s => s.trim());\n const fns = names.map(name => {\n if (typeof mod[name] !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${name}\" not found or not a function`);\n }\n return mod[name] as WoodMiddlewareFn;\n });\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else {\n fn = mod[selectorPart];\n if (typeof fn !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${selectorPart}\" not found or not a function`);\n }\n }\n\n this.cache.set(spec, fn);\n return fn;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,sBAA8B;AAK9B,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,YAAAA,QAAK,WAAW,IAAI,QAAI,+BAAc,IAAI,EAAE,OAAO;AAC5D;AAEO,MAAM,mBAAmB;AAAA,EAI9B,YAAY,eAAuB;AAFnC,SAAQ,QAAQ,oBAAI,IAA8B;AAGhD,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAQ,MAAyC;AACrD,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAClC,QAAI,OAAQ,QAAO;AAEnB,UAAM,CAAC,UAAU,YAAY,IAAI,KAAK,SAAS,GAAG,IAC9C,KAAK,MAAM,KAAK,CAAC,IACjB,CAAC,MAAM,SAAS;AAEpB,UAAM,UAAU,SAAS,QAAQ,OAAO,YAAAA,QAAK,GAAG;AAChD,UAAM,WAAW,YAAAA,QAAK,QAAQ,KAAK,SAAS,OAAO;AAEnD,UAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;AAEnD,QAAI;AACJ,QAAI,iBAAiB,WAAW;AAC9B,WAAK,IAAI;AAAA,IACX,WAAW,iBAAiB,KAAK;AAC/B,YAAM,MAAM,OAAO,OAAO,GAAG,EAAE,OAAO,OAAK,OAAO,MAAM,UAAU;AAClE,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,WAAW,aAAa,SAAS,GAAG,GAAG;AACrC,YAAM,QAAQ,aAAa,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACvD,YAAM,MAAM,MAAM,IAAI,UAAQ;AAC5B,YAAI,OAAO,IAAI,IAAI,MAAM,YAAY;AACnC,gBAAM,IAAI,MAAM,eAAe,IAAI,cAAc,IAAI,+BAA+B;AAAA,QACtF;AACA,eAAO,IAAI,IAAI;AAAA,MACjB,CAAC;AACD,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,OAAO;AACL,WAAK,IAAI,YAAY;AACrB,UAAI,OAAO,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,eAAe,IAAI,cAAc,YAAY,+BAA+B;AAAA,MAC9F;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,MAAM,EAAE;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;","names":["path"]}
1
+ {"version":3,"sources":["../../src/middleware/middleware_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport type { WoodMiddlewareFn } from '../types/index.cjs';\n\n// Node's ESM loader rejects raw absolute Windows paths (`C:\\...`) — they must\n// be file:// URLs. Bare specifiers and relative paths pass through unchanged.\nfunction toImportSpecifier(spec: string): string {\n return path.isAbsolute(spec) ? pathToFileURL(spec).href : spec;\n}\n\nexport class MiddlewareResolver {\n private baseDir: string;\n private cache = new Map<string, WoodMiddlewareFn>();\n private registered = new Map<string, WoodMiddlewareFn>();\n\n constructor(middlewareDir: string) {\n this.baseDir = middlewareDir;\n }\n\n /**\n * Pre-register the executable satisfying a production middleware identity.\n * Mirrors controller pre-registration: bundled builds register generated\n * bindings instead of importing from the filesystem, and test environments\n * replace an identity's executable while production topology (membership,\n * order, inheritance) still comes from source. Last registration wins.\n */\n register(spec: string, fn: WoodMiddlewareFn): void {\n if (typeof fn !== 'function') {\n throw new Error(`registerMiddleware(\"${spec}\"): expected a function, got ${typeof fn}`);\n }\n this.registered.set(spec, fn);\n }\n\n /** Whether an identity has a registered executable. */\n has(spec: string): boolean {\n return this.registered.has(spec);\n }\n\n /**\n * Resolve a middleware spec like \"auth.admin:is_admin\" into a function.\n *\n * Registered executables win; otherwise the spec resolves from the\n * filesystem. Format: \"file.path:function_selector\"\n * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts\n * - function_selector: named export, \"*\" for all, comma-separated for multiple\n * - If no colon, use default export\n */\n async resolve(spec: string): Promise<WoodMiddlewareFn> {\n const registered = this.registered.get(spec);\n if (registered) return registered;\n\n const cached = this.cache.get(spec);\n if (cached) return cached;\n\n const [filePart, selectorPart] = spec.includes(':')\n ? spec.split(':', 2) as [string, string]\n : [spec, 'default'];\n\n const relPath = filePart.replace(/\\./g, path.sep);\n const fullPath = path.resolve(this.baseDir, relPath);\n\n const mod = await import(toImportSpecifier(fullPath));\n\n let fn: WoodMiddlewareFn;\n if (selectorPart === 'default') {\n fn = mod.default;\n } else if (selectorPart === '*') {\n const fns = Object.values(mod).filter(v => typeof v === 'function') as WoodMiddlewareFn[];\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else if (selectorPart.includes(',')) {\n const names = selectorPart.split(',').map(s => s.trim());\n const fns = names.map(name => {\n if (typeof mod[name] !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${name}\" not found or not a function`);\n }\n return mod[name] as WoodMiddlewareFn;\n });\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else {\n fn = mod[selectorPart];\n if (typeof fn !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${selectorPart}\" not found or not a function`);\n }\n }\n\n this.cache.set(spec, fn);\n return fn;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,sBAA8B;AAK9B,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,YAAAA,QAAK,WAAW,IAAI,QAAI,+BAAc,IAAI,EAAE,OAAO;AAC5D;AAEO,MAAM,mBAAmB;AAAA,EAK9B,YAAY,eAAuB;AAHnC,SAAQ,QAAQ,oBAAI,IAA8B;AAClD,SAAQ,aAAa,oBAAI,IAA8B;AAGrD,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,MAAc,IAA4B;AACjD,QAAI,OAAO,OAAO,YAAY;AAC5B,YAAM,IAAI,MAAM,uBAAuB,IAAI,gCAAgC,OAAO,EAAE,EAAE;AAAA,IACxF;AACA,SAAK,WAAW,IAAI,MAAM,EAAE;AAAA,EAC9B;AAAA;AAAA,EAGA,IAAI,MAAuB;AACzB,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAQ,MAAyC;AACrD,UAAM,aAAa,KAAK,WAAW,IAAI,IAAI;AAC3C,QAAI,WAAY,QAAO;AAEvB,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAClC,QAAI,OAAQ,QAAO;AAEnB,UAAM,CAAC,UAAU,YAAY,IAAI,KAAK,SAAS,GAAG,IAC9C,KAAK,MAAM,KAAK,CAAC,IACjB,CAAC,MAAM,SAAS;AAEpB,UAAM,UAAU,SAAS,QAAQ,OAAO,YAAAA,QAAK,GAAG;AAChD,UAAM,WAAW,YAAAA,QAAK,QAAQ,KAAK,SAAS,OAAO;AAEnD,UAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;AAEnD,QAAI;AACJ,QAAI,iBAAiB,WAAW;AAC9B,WAAK,IAAI;AAAA,IACX,WAAW,iBAAiB,KAAK;AAC/B,YAAM,MAAM,OAAO,OAAO,GAAG,EAAE,OAAO,OAAK,OAAO,MAAM,UAAU;AAClE,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,WAAW,aAAa,SAAS,GAAG,GAAG;AACrC,YAAM,QAAQ,aAAa,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACvD,YAAM,MAAM,MAAM,IAAI,UAAQ;AAC5B,YAAI,OAAO,IAAI,IAAI,MAAM,YAAY;AACnC,gBAAM,IAAI,MAAM,eAAe,IAAI,cAAc,IAAI,+BAA+B;AAAA,QACtF;AACA,eAAO,IAAI,IAAI;AAAA,MACjB,CAAC;AACD,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,OAAO;AACL,WAAK,IAAI,YAAY;AACrB,UAAI,OAAO,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,eAAe,IAAI,cAAc,YAAY,+BAA+B;AAAA,MAC9F;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,MAAM,EAAE;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;","names":["path"]}
@@ -3,11 +3,23 @@ import { WoodMiddlewareFn } from '../types/context.cjs';
3
3
  declare class MiddlewareResolver {
4
4
  private baseDir;
5
5
  private cache;
6
+ private registered;
6
7
  constructor(middlewareDir: string);
8
+ /**
9
+ * Pre-register the executable satisfying a production middleware identity.
10
+ * Mirrors controller pre-registration: bundled builds register generated
11
+ * bindings instead of importing from the filesystem, and test environments
12
+ * replace an identity's executable while production topology (membership,
13
+ * order, inheritance) still comes from source. Last registration wins.
14
+ */
15
+ register(spec: string, fn: WoodMiddlewareFn): void;
16
+ /** Whether an identity has a registered executable. */
17
+ has(spec: string): boolean;
7
18
  /**
8
19
  * Resolve a middleware spec like "auth.admin:is_admin" into a function.
9
20
  *
10
- * Format: "file.path:function_selector"
21
+ * Registered executables win; otherwise the spec resolves from the
22
+ * filesystem. Format: "file.path:function_selector"
11
23
  * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts
12
24
  * - function_selector: named export, "*" for all, comma-separated for multiple
13
25
  * - If no colon, use default export
@@ -3,11 +3,23 @@ import { WoodMiddlewareFn } from '../types/context.js';
3
3
  declare class MiddlewareResolver {
4
4
  private baseDir;
5
5
  private cache;
6
+ private registered;
6
7
  constructor(middlewareDir: string);
8
+ /**
9
+ * Pre-register the executable satisfying a production middleware identity.
10
+ * Mirrors controller pre-registration: bundled builds register generated
11
+ * bindings instead of importing from the filesystem, and test environments
12
+ * replace an identity's executable while production topology (membership,
13
+ * order, inheritance) still comes from source. Last registration wins.
14
+ */
15
+ register(spec: string, fn: WoodMiddlewareFn): void;
16
+ /** Whether an identity has a registered executable. */
17
+ has(spec: string): boolean;
7
18
  /**
8
19
  * Resolve a middleware spec like "auth.admin:is_admin" into a function.
9
20
  *
10
- * Format: "file.path:function_selector"
21
+ * Registered executables win; otherwise the spec resolves from the
22
+ * filesystem. Format: "file.path:function_selector"
11
23
  * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts
12
24
  * - function_selector: named export, "*" for all, comma-separated for multiple
13
25
  * - If no colon, use default export
@@ -6,17 +6,38 @@ function toImportSpecifier(spec) {
6
6
  class MiddlewareResolver {
7
7
  constructor(middlewareDir) {
8
8
  this.cache = /* @__PURE__ */ new Map();
9
+ this.registered = /* @__PURE__ */ new Map();
9
10
  this.baseDir = middlewareDir;
10
11
  }
12
+ /**
13
+ * Pre-register the executable satisfying a production middleware identity.
14
+ * Mirrors controller pre-registration: bundled builds register generated
15
+ * bindings instead of importing from the filesystem, and test environments
16
+ * replace an identity's executable while production topology (membership,
17
+ * order, inheritance) still comes from source. Last registration wins.
18
+ */
19
+ register(spec, fn) {
20
+ if (typeof fn !== "function") {
21
+ throw new Error(`registerMiddleware("${spec}"): expected a function, got ${typeof fn}`);
22
+ }
23
+ this.registered.set(spec, fn);
24
+ }
25
+ /** Whether an identity has a registered executable. */
26
+ has(spec) {
27
+ return this.registered.has(spec);
28
+ }
11
29
  /**
12
30
  * Resolve a middleware spec like "auth.admin:is_admin" into a function.
13
31
  *
14
- * Format: "file.path:function_selector"
32
+ * Registered executables win; otherwise the spec resolves from the
33
+ * filesystem. Format: "file.path:function_selector"
15
34
  * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts
16
35
  * - function_selector: named export, "*" for all, comma-separated for multiple
17
36
  * - If no colon, use default export
18
37
  */
19
38
  async resolve(spec) {
39
+ const registered = this.registered.get(spec);
40
+ if (registered) return registered;
20
41
  const cached = this.cache.get(spec);
21
42
  if (cached) return cached;
22
43
  const [filePart, selectorPart] = spec.includes(":") ? spec.split(":", 2) : [spec, "default"];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/middleware/middleware_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport type { WoodMiddlewareFn } from '../types/index.js';\n\n// Node's ESM loader rejects raw absolute Windows paths (`C:\\...`) — they must\n// be file:// URLs. Bare specifiers and relative paths pass through unchanged.\nfunction toImportSpecifier(spec: string): string {\n return path.isAbsolute(spec) ? pathToFileURL(spec).href : spec;\n}\n\nexport class MiddlewareResolver {\n private baseDir: string;\n private cache = new Map<string, WoodMiddlewareFn>();\n\n constructor(middlewareDir: string) {\n this.baseDir = middlewareDir;\n }\n\n /**\n * Resolve a middleware spec like \"auth.admin:is_admin\" into a function.\n *\n * Format: \"file.path:function_selector\"\n * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts\n * - function_selector: named export, \"*\" for all, comma-separated for multiple\n * - If no colon, use default export\n */\n async resolve(spec: string): Promise<WoodMiddlewareFn> {\n const cached = this.cache.get(spec);\n if (cached) return cached;\n\n const [filePart, selectorPart] = spec.includes(':')\n ? spec.split(':', 2) as [string, string]\n : [spec, 'default'];\n\n const relPath = filePart.replace(/\\./g, path.sep);\n const fullPath = path.resolve(this.baseDir, relPath);\n\n const mod = await import(toImportSpecifier(fullPath));\n\n let fn: WoodMiddlewareFn;\n if (selectorPart === 'default') {\n fn = mod.default;\n } else if (selectorPart === '*') {\n const fns = Object.values(mod).filter(v => typeof v === 'function') as WoodMiddlewareFn[];\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else if (selectorPart.includes(',')) {\n const names = selectorPart.split(',').map(s => s.trim());\n const fns = names.map(name => {\n if (typeof mod[name] !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${name}\" not found or not a function`);\n }\n return mod[name] as WoodMiddlewareFn;\n });\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else {\n fn = mod[selectorPart];\n if (typeof fn !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${selectorPart}\" not found or not a function`);\n }\n }\n\n this.cache.set(spec, fn);\n return fn;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"],"mappings":"AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAK9B,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,KAAK,WAAW,IAAI,IAAI,cAAc,IAAI,EAAE,OAAO;AAC5D;AAEO,MAAM,mBAAmB;AAAA,EAI9B,YAAY,eAAuB;AAFnC,SAAQ,QAAQ,oBAAI,IAA8B;AAGhD,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAQ,MAAyC;AACrD,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAClC,QAAI,OAAQ,QAAO;AAEnB,UAAM,CAAC,UAAU,YAAY,IAAI,KAAK,SAAS,GAAG,IAC9C,KAAK,MAAM,KAAK,CAAC,IACjB,CAAC,MAAM,SAAS;AAEpB,UAAM,UAAU,SAAS,QAAQ,OAAO,KAAK,GAAG;AAChD,UAAM,WAAW,KAAK,QAAQ,KAAK,SAAS,OAAO;AAEnD,UAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;AAEnD,QAAI;AACJ,QAAI,iBAAiB,WAAW;AAC9B,WAAK,IAAI;AAAA,IACX,WAAW,iBAAiB,KAAK;AAC/B,YAAM,MAAM,OAAO,OAAO,GAAG,EAAE,OAAO,OAAK,OAAO,MAAM,UAAU;AAClE,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,WAAW,aAAa,SAAS,GAAG,GAAG;AACrC,YAAM,QAAQ,aAAa,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACvD,YAAM,MAAM,MAAM,IAAI,UAAQ;AAC5B,YAAI,OAAO,IAAI,IAAI,MAAM,YAAY;AACnC,gBAAM,IAAI,MAAM,eAAe,IAAI,cAAc,IAAI,+BAA+B;AAAA,QACtF;AACA,eAAO,IAAI,IAAI;AAAA,MACjB,CAAC;AACD,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,OAAO;AACL,WAAK,IAAI,YAAY;AACrB,UAAI,OAAO,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,eAAe,IAAI,cAAc,YAAY,+BAA+B;AAAA,MAC9F;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,MAAM,EAAE;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/middleware/middleware_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport type { WoodMiddlewareFn } from '../types/index.js';\n\n// Node's ESM loader rejects raw absolute Windows paths (`C:\\...`) — they must\n// be file:// URLs. Bare specifiers and relative paths pass through unchanged.\nfunction toImportSpecifier(spec: string): string {\n return path.isAbsolute(spec) ? pathToFileURL(spec).href : spec;\n}\n\nexport class MiddlewareResolver {\n private baseDir: string;\n private cache = new Map<string, WoodMiddlewareFn>();\n private registered = new Map<string, WoodMiddlewareFn>();\n\n constructor(middlewareDir: string) {\n this.baseDir = middlewareDir;\n }\n\n /**\n * Pre-register the executable satisfying a production middleware identity.\n * Mirrors controller pre-registration: bundled builds register generated\n * bindings instead of importing from the filesystem, and test environments\n * replace an identity's executable while production topology (membership,\n * order, inheritance) still comes from source. Last registration wins.\n */\n register(spec: string, fn: WoodMiddlewareFn): void {\n if (typeof fn !== 'function') {\n throw new Error(`registerMiddleware(\"${spec}\"): expected a function, got ${typeof fn}`);\n }\n this.registered.set(spec, fn);\n }\n\n /** Whether an identity has a registered executable. */\n has(spec: string): boolean {\n return this.registered.has(spec);\n }\n\n /**\n * Resolve a middleware spec like \"auth.admin:is_admin\" into a function.\n *\n * Registered executables win; otherwise the spec resolves from the\n * filesystem. Format: \"file.path:function_selector\"\n * - Dots in file path become path separators: auth.admin -> middleware/auth/admin.ts\n * - function_selector: named export, \"*\" for all, comma-separated for multiple\n * - If no colon, use default export\n */\n async resolve(spec: string): Promise<WoodMiddlewareFn> {\n const registered = this.registered.get(spec);\n if (registered) return registered;\n\n const cached = this.cache.get(spec);\n if (cached) return cached;\n\n const [filePart, selectorPart] = spec.includes(':')\n ? spec.split(':', 2) as [string, string]\n : [spec, 'default'];\n\n const relPath = filePart.replace(/\\./g, path.sep);\n const fullPath = path.resolve(this.baseDir, relPath);\n\n const mod = await import(toImportSpecifier(fullPath));\n\n let fn: WoodMiddlewareFn;\n if (selectorPart === 'default') {\n fn = mod.default;\n } else if (selectorPart === '*') {\n const fns = Object.values(mod).filter(v => typeof v === 'function') as WoodMiddlewareFn[];\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else if (selectorPart.includes(',')) {\n const names = selectorPart.split(',').map(s => s.trim());\n const fns = names.map(name => {\n if (typeof mod[name] !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${name}\" not found or not a function`);\n }\n return mod[name] as WoodMiddlewareFn;\n });\n fn = async (ctx) => {\n for (const f of fns) await f(ctx);\n };\n } else {\n fn = mod[selectorPart];\n if (typeof fn !== 'function') {\n throw new Error(`Middleware \"${spec}\": export \"${selectorPart}\" not found or not a function`);\n }\n }\n\n this.cache.set(spec, fn);\n return fn;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"],"mappings":"AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAK9B,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,KAAK,WAAW,IAAI,IAAI,cAAc,IAAI,EAAE,OAAO;AAC5D;AAEO,MAAM,mBAAmB;AAAA,EAK9B,YAAY,eAAuB;AAHnC,SAAQ,QAAQ,oBAAI,IAA8B;AAClD,SAAQ,aAAa,oBAAI,IAA8B;AAGrD,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,MAAc,IAA4B;AACjD,QAAI,OAAO,OAAO,YAAY;AAC5B,YAAM,IAAI,MAAM,uBAAuB,IAAI,gCAAgC,OAAO,EAAE,EAAE;AAAA,IACxF;AACA,SAAK,WAAW,IAAI,MAAM,EAAE;AAAA,EAC9B;AAAA;AAAA,EAGA,IAAI,MAAuB;AACzB,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAQ,MAAyC;AACrD,UAAM,aAAa,KAAK,WAAW,IAAI,IAAI;AAC3C,QAAI,WAAY,QAAO;AAEvB,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAClC,QAAI,OAAQ,QAAO;AAEnB,UAAM,CAAC,UAAU,YAAY,IAAI,KAAK,SAAS,GAAG,IAC9C,KAAK,MAAM,KAAK,CAAC,IACjB,CAAC,MAAM,SAAS;AAEpB,UAAM,UAAU,SAAS,QAAQ,OAAO,KAAK,GAAG;AAChD,UAAM,WAAW,KAAK,QAAQ,KAAK,SAAS,OAAO;AAEnD,UAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;AAEnD,QAAI;AACJ,QAAI,iBAAiB,WAAW;AAC9B,WAAK,IAAI;AAAA,IACX,WAAW,iBAAiB,KAAK;AAC/B,YAAM,MAAM,OAAO,OAAO,GAAG,EAAE,OAAO,OAAK,OAAO,MAAM,UAAU;AAClE,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,WAAW,aAAa,SAAS,GAAG,GAAG;AACrC,YAAM,QAAQ,aAAa,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACvD,YAAM,MAAM,MAAM,IAAI,UAAQ;AAC5B,YAAI,OAAO,IAAI,IAAI,MAAM,YAAY;AACnC,gBAAM,IAAI,MAAM,eAAe,IAAI,cAAc,IAAI,+BAA+B;AAAA,QACtF;AACA,eAAO,IAAI,IAAI;AAAA,MACjB,CAAC;AACD,WAAK,OAAO,QAAQ;AAClB,mBAAW,KAAK,IAAK,OAAM,EAAE,GAAG;AAAA,MAClC;AAAA,IACF,OAAO;AACL,WAAK,IAAI,YAAY;AACrB,UAAI,OAAO,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,eAAe,IAAI,cAAc,YAAY,+BAA+B;AAAA,MAC9F;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,MAAM,EAAE;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;","names":[]}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var automation_introspection_exports = {};
20
+ __export(automation_introspection_exports, {
21
+ WOOD_AUTOMATION_GLOBAL_KEY: () => WOOD_AUTOMATION_GLOBAL_KEY,
22
+ installAutomationIntrospection: () => installAutomationIntrospection
23
+ });
24
+ module.exports = __toCommonJS(automation_introspection_exports);
25
+ var import_index = require("./index.cjs");
26
+ const WOOD_AUTOMATION_GLOBAL_KEY = "__NOEGO_WOOD_AUTOMATION__";
27
+ function toRoute(entry) {
28
+ if (!entry) {
29
+ return null;
30
+ }
31
+ return { page: entry.page, params: { ...entry.params }, query: { ...entry.query } };
32
+ }
33
+ function installAutomationIntrospection(options = {}) {
34
+ const globalObject = options.globalObject ?? globalThis;
35
+ const navigation = (0, import_index.getNavigation)();
36
+ let routeRevision = 0;
37
+ const listeners = /* @__PURE__ */ new Set();
38
+ const unsubscribeNavigation = navigation.subscribe((entry) => {
39
+ routeRevision += 1;
40
+ const event = { kind: "route", entry: toRoute(entry) };
41
+ for (const listener of listeners) {
42
+ listener(event);
43
+ }
44
+ });
45
+ const surface = {
46
+ version: 1,
47
+ snapshot: () => ({
48
+ version: 1,
49
+ windowId: options.windowId ?? null,
50
+ currentRoute: toRoute(navigation.getCurrent()),
51
+ navigationDepth: navigation.getPages().length,
52
+ rendererReady: true,
53
+ pendingWork: {
54
+ // Bounded placeholders until render/bridge instrumentation lands;
55
+ // consumers must treat unknown pending work as zero, not omit checks.
56
+ bridgeCalls: 0,
57
+ renders: 0,
58
+ animations: 0
59
+ }
60
+ }),
61
+ waitForIdle: (waitOptions) => {
62
+ const timeoutMs = waitOptions?.timeoutMs ?? 2e3;
63
+ const idleFramesRequired = waitOptions?.idleFrames ?? 3;
64
+ const raf = typeof requestAnimationFrame === "function" ? (cb) => requestAnimationFrame(() => cb()) : (cb) => void setTimeout(cb, 16);
65
+ return new Promise((resolve) => {
66
+ const startedAt = Date.now();
67
+ let lastSeenRevision = routeRevision;
68
+ let idleFrames = 0;
69
+ const step = () => {
70
+ if (Date.now() - startedAt > timeoutMs) {
71
+ resolve(false);
72
+ return;
73
+ }
74
+ if (routeRevision !== lastSeenRevision) {
75
+ lastSeenRevision = routeRevision;
76
+ idleFrames = 0;
77
+ } else {
78
+ idleFrames += 1;
79
+ if (idleFrames >= idleFramesRequired) {
80
+ resolve(true);
81
+ return;
82
+ }
83
+ }
84
+ raf(step);
85
+ };
86
+ raf(step);
87
+ });
88
+ },
89
+ subscribe: (listener) => {
90
+ listeners.add(listener);
91
+ return () => {
92
+ listeners.delete(listener);
93
+ };
94
+ }
95
+ };
96
+ globalObject[WOOD_AUTOMATION_GLOBAL_KEY] = surface;
97
+ return () => {
98
+ unsubscribeNavigation();
99
+ listeners.clear();
100
+ if (globalObject[WOOD_AUTOMATION_GLOBAL_KEY] === surface) {
101
+ delete globalObject[WOOD_AUTOMATION_GLOBAL_KEY];
102
+ }
103
+ };
104
+ }
105
+ // Annotate the CommonJS export names for ESM import in node:
106
+ 0 && (module.exports = {
107
+ WOOD_AUTOMATION_GLOBAL_KEY,
108
+ installAutomationIntrospection
109
+ });
110
+ //# sourceMappingURL=automation_introspection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/navigation/automation_introspection.ts"],"sourcesContent":["/**\n * Dev/test-only automation introspection (Axe.md AXE-WP-02).\n *\n * Exposes a narrow, versioned inspection surface for the Axe live driver:\n * current route, readiness, and route-change subscription. It exposes no\n * privileged operations.\n *\n * Deviation from the spec's `bridge.__automation` shape: the preload bridge\n * (`__NOEGO_WOOD_BRIDGE__`) is a sealed contextBridge object that renderer\n * code cannot extend, so the surface is installed as the sibling main-world\n * global `__NOEGO_WOOD_AUTOMATION__`. Axe reads it the same way.\n *\n * This module lives in the renderer bundle. It must only be installed in\n * development and explicit test builds — the generated renderer app gates the\n * install call; this module never self-installs on import.\n */\n\nimport { getNavigation, type NavigationEntry } from './index.cjs';\n\nexport const WOOD_AUTOMATION_GLOBAL_KEY = '__NOEGO_WOOD_AUTOMATION__';\n\nexport interface WoodAutomationSnapshot {\n version: 1;\n windowId: string | null;\n currentRoute: {\n page: string;\n params: Record<string, string>;\n query: Record<string, string>;\n } | null;\n navigationDepth: number;\n rendererReady: boolean;\n pendingWork: {\n bridgeCalls: number;\n renders: number;\n animations: number;\n };\n}\n\nexport type WoodAutomationEvent =\n | { kind: 'route'; entry: WoodAutomationSnapshot['currentRoute'] };\n\nexport interface WoodAutomationIntrospection {\n version: 1;\n snapshot: () => WoodAutomationSnapshot;\n waitForIdle: (options?: { timeoutMs?: number; idleFrames?: number }) => Promise<boolean>;\n subscribe: (listener: (event: WoodAutomationEvent) => void) => () => void;\n}\n\nexport interface InstallAutomationIntrospectionOptions {\n /** Wood window identity when known at install time. */\n windowId?: string | null;\n /** Override for tests; defaults to `globalThis`. */\n globalObject?: Record<string, unknown>;\n}\n\nfunction toRoute(entry: NavigationEntry | null): WoodAutomationSnapshot['currentRoute'] {\n if (!entry) {\n return null;\n }\n return { page: entry.page, params: { ...entry.params }, query: { ...entry.query } };\n}\n\n/**\n * Install the introspection global. Idempotent: repeated installs replace the\n * previous surface (fresh navigation subscription, updated windowId).\n * Returns an uninstall function.\n */\nexport function installAutomationIntrospection(\n options: InstallAutomationIntrospectionOptions = {},\n): () => void {\n const globalObject = options.globalObject ?? (globalThis as unknown as Record<string, unknown>);\n const navigation = getNavigation();\n\n let routeRevision = 0;\n const listeners = new Set<(event: WoodAutomationEvent) => void>();\n\n const unsubscribeNavigation = navigation.subscribe((entry) => {\n routeRevision += 1;\n const event: WoodAutomationEvent = { kind: 'route', entry: toRoute(entry) };\n for (const listener of listeners) {\n listener(event);\n }\n });\n\n const surface: WoodAutomationIntrospection = {\n version: 1,\n snapshot: () => ({\n version: 1,\n windowId: options.windowId ?? null,\n currentRoute: toRoute(navigation.getCurrent()),\n navigationDepth: navigation.getPages().length,\n rendererReady: true,\n pendingWork: {\n // Bounded placeholders until render/bridge instrumentation lands;\n // consumers must treat unknown pending work as zero, not omit checks.\n bridgeCalls: 0,\n renders: 0,\n animations: 0,\n },\n }),\n waitForIdle: (waitOptions) => {\n const timeoutMs = waitOptions?.timeoutMs ?? 2_000;\n const idleFramesRequired = waitOptions?.idleFrames ?? 3;\n const raf: (cb: () => void) => void =\n typeof requestAnimationFrame === 'function'\n ? (cb) => requestAnimationFrame(() => cb())\n : (cb) => void setTimeout(cb, 16);\n\n return new Promise<boolean>((resolve) => {\n const startedAt = Date.now();\n let lastSeenRevision = routeRevision;\n let idleFrames = 0;\n\n const step = (): void => {\n if (Date.now() - startedAt > timeoutMs) {\n resolve(false);\n return;\n }\n if (routeRevision !== lastSeenRevision) {\n lastSeenRevision = routeRevision;\n idleFrames = 0;\n } else {\n idleFrames += 1;\n if (idleFrames >= idleFramesRequired) {\n resolve(true);\n return;\n }\n }\n raf(step);\n };\n\n raf(step);\n });\n },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n\n globalObject[WOOD_AUTOMATION_GLOBAL_KEY] = surface;\n\n return () => {\n unsubscribeNavigation();\n listeners.clear();\n if (globalObject[WOOD_AUTOMATION_GLOBAL_KEY] === surface) {\n delete globalObject[WOOD_AUTOMATION_GLOBAL_KEY];\n }\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,mBAAoD;AAE7C,MAAM,6BAA6B;AAoC1C,SAAS,QAAQ,OAAuE;AACtF,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,QAAQ,EAAE,GAAG,MAAM,OAAO,GAAG,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE;AACpF;AAOO,SAAS,+BACd,UAAiD,CAAC,GACtC;AACZ,QAAM,eAAe,QAAQ,gBAAiB;AAC9C,QAAM,iBAAa,4BAAc;AAEjC,MAAI,gBAAgB;AACpB,QAAM,YAAY,oBAAI,IAA0C;AAEhE,QAAM,wBAAwB,WAAW,UAAU,CAAC,UAAU;AAC5D,qBAAiB;AACjB,UAAM,QAA6B,EAAE,MAAM,SAAS,OAAO,QAAQ,KAAK,EAAE;AAC1E,eAAW,YAAY,WAAW;AAChC,eAAS,KAAK;AAAA,IAChB;AAAA,EACF,CAAC;AAED,QAAM,UAAuC;AAAA,IAC3C,SAAS;AAAA,IACT,UAAU,OAAO;AAAA,MACf,SAAS;AAAA,MACT,UAAU,QAAQ,YAAY;AAAA,MAC9B,cAAc,QAAQ,WAAW,WAAW,CAAC;AAAA,MAC7C,iBAAiB,WAAW,SAAS,EAAE;AAAA,MACvC,eAAe;AAAA,MACf,aAAa;AAAA;AAAA;AAAA,QAGX,aAAa;AAAA,QACb,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,aAAa,CAAC,gBAAgB;AAC5B,YAAM,YAAY,aAAa,aAAa;AAC5C,YAAM,qBAAqB,aAAa,cAAc;AACtD,YAAM,MACJ,OAAO,0BAA0B,aAC7B,CAAC,OAAO,sBAAsB,MAAM,GAAG,CAAC,IACxC,CAAC,OAAO,KAAK,WAAW,IAAI,EAAE;AAEpC,aAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,cAAM,YAAY,KAAK,IAAI;AAC3B,YAAI,mBAAmB;AACvB,YAAI,aAAa;AAEjB,cAAM,OAAO,MAAY;AACvB,cAAI,KAAK,IAAI,IAAI,YAAY,WAAW;AACtC,oBAAQ,KAAK;AACb;AAAA,UACF;AACA,cAAI,kBAAkB,kBAAkB;AACtC,+BAAmB;AACnB,yBAAa;AAAA,UACf,OAAO;AACL,0BAAc;AACd,gBAAI,cAAc,oBAAoB;AACpC,sBAAQ,IAAI;AACZ;AAAA,YACF;AAAA,UACF;AACA,cAAI,IAAI;AAAA,QACV;AAEA,YAAI,IAAI;AAAA,MACV,CAAC;AAAA,IACH;AAAA,IACA,WAAW,CAAC,aAAa;AACvB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,eAAa,0BAA0B,IAAI;AAE3C,SAAO,MAAM;AACX,0BAAsB;AACtB,cAAU,MAAM;AAChB,QAAI,aAAa,0BAA0B,MAAM,SAAS;AACxD,aAAO,aAAa,0BAA0B;AAAA,IAChD;AAAA,EACF;AACF;","names":[]}