@noego/wood 0.4.10 → 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 (382) hide show
  1. package/README.md +118 -42
  2. package/dist/bridge/backend_bridge.cjs.map +1 -1
  3. package/dist/bridge/backend_bridge.js.map +1 -1
  4. package/dist/client/index.cjs +78 -21
  5. package/dist/client/index.cjs.map +1 -1
  6. package/dist/client/index.d.cts +18 -3
  7. package/dist/client/index.d.ts +18 -3
  8. package/dist/client/index.js +80 -22
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/client/renderer_log_transport.cjs +151 -0
  11. package/dist/client/renderer_log_transport.cjs.map +1 -0
  12. package/dist/client/renderer_log_transport.d.cts +54 -0
  13. package/dist/client/renderer_log_transport.d.ts +54 -0
  14. package/dist/client/renderer_log_transport.js +123 -0
  15. package/dist/client/renderer_log_transport.js.map +1 -0
  16. package/dist/codegen/controller_registration_generator.cjs +13 -2
  17. package/dist/codegen/controller_registration_generator.cjs.map +1 -1
  18. package/dist/codegen/controller_registration_generator.d.cts +12 -1
  19. package/dist/codegen/controller_registration_generator.d.ts +12 -1
  20. package/dist/codegen/controller_registration_generator.js +10 -1
  21. package/dist/codegen/controller_registration_generator.js.map +1 -1
  22. package/dist/codegen/index.d.cts +1 -0
  23. package/dist/codegen/index.d.ts +1 -0
  24. package/dist/codegen/preload_generator.cjs +13 -6
  25. package/dist/codegen/preload_generator.cjs.map +1 -1
  26. package/dist/codegen/preload_generator.d.cts +11 -2
  27. package/dist/codegen/preload_generator.d.ts +11 -2
  28. package/dist/codegen/preload_generator.js +13 -6
  29. package/dist/codegen/preload_generator.js.map +1 -1
  30. package/dist/codegen/renderer_app_generator.cjs +78 -42
  31. package/dist/codegen/renderer_app_generator.cjs.map +1 -1
  32. package/dist/codegen/renderer_app_generator.js +78 -42
  33. package/dist/codegen/renderer_app_generator.js.map +1 -1
  34. package/dist/codegen/type_generator.cjs +1 -0
  35. package/dist/codegen/type_generator.cjs.map +1 -1
  36. package/dist/codegen/type_generator.js +1 -0
  37. package/dist/codegen/type_generator.js.map +1 -1
  38. package/dist/config/config_parser.cjs +95 -4
  39. package/dist/config/config_parser.cjs.map +1 -1
  40. package/dist/config/config_parser.d.cts +10 -2
  41. package/dist/config/config_parser.d.ts +10 -2
  42. package/dist/config/config_parser.js +92 -3
  43. package/dist/config/config_parser.js.map +1 -1
  44. package/dist/config/index.cjs +6 -2
  45. package/dist/config/index.cjs.map +1 -1
  46. package/dist/config/index.d.cts +2 -2
  47. package/dist/config/index.d.ts +2 -2
  48. package/dist/config/index.js +8 -2
  49. package/dist/config/index.js.map +1 -1
  50. package/dist/controller/controller_resolver.cjs +51 -3
  51. package/dist/controller/controller_resolver.cjs.map +1 -1
  52. package/dist/controller/controller_resolver.d.cts +27 -4
  53. package/dist/controller/controller_resolver.d.ts +27 -4
  54. package/dist/controller/controller_resolver.js +48 -2
  55. package/dist/controller/controller_resolver.js.map +1 -1
  56. package/dist/controller/index.cjs +6 -2
  57. package/dist/controller/index.cjs.map +1 -1
  58. package/dist/controller/index.d.cts +1 -1
  59. package/dist/controller/index.d.ts +1 -1
  60. package/dist/controller/index.js +4 -2
  61. package/dist/controller/index.js.map +1 -1
  62. package/dist/dev/wood_dev_server.cjs +4 -1
  63. package/dist/dev/wood_dev_server.cjs.map +1 -1
  64. package/dist/dev/wood_dev_server.js +5 -2
  65. package/dist/dev/wood_dev_server.js.map +1 -1
  66. package/dist/dev/yaml_watcher.cjs +1 -1
  67. package/dist/dev/yaml_watcher.cjs.map +1 -1
  68. package/dist/dev/yaml_watcher.d.cts +4 -0
  69. package/dist/dev/yaml_watcher.d.ts +4 -0
  70. package/dist/dev/yaml_watcher.js +1 -1
  71. package/dist/dev/yaml_watcher.js.map +1 -1
  72. package/dist/frontend/frontend_lifecycle.cjs +74 -0
  73. package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
  74. package/dist/frontend/frontend_lifecycle.d.cts +50 -0
  75. package/dist/frontend/frontend_lifecycle.d.ts +50 -0
  76. package/dist/frontend/frontend_lifecycle.js +50 -0
  77. package/dist/frontend/frontend_lifecycle.js.map +1 -0
  78. package/dist/frontend/frontend_page.cjs +122 -0
  79. package/dist/frontend/frontend_page.cjs.map +1 -0
  80. package/dist/frontend/frontend_page.d.cts +62 -0
  81. package/dist/frontend/frontend_page.d.ts +62 -0
  82. package/dist/frontend/frontend_page.js +98 -0
  83. package/dist/frontend/frontend_page.js.map +1 -0
  84. package/dist/frontend/frontend_surface.cjs +249 -0
  85. package/dist/frontend/frontend_surface.cjs.map +1 -0
  86. package/dist/frontend/frontend_surface.d.cts +64 -0
  87. package/dist/frontend/frontend_surface.d.ts +64 -0
  88. package/dist/frontend/frontend_surface.js +224 -0
  89. package/dist/frontend/frontend_surface.js.map +1 -0
  90. package/dist/frontend/index.cjs +52 -0
  91. package/dist/frontend/index.cjs.map +1 -0
  92. package/dist/frontend/index.d.cts +10 -0
  93. package/dist/frontend/index.d.ts +10 -0
  94. package/dist/frontend/index.js +19 -0
  95. package/dist/frontend/index.js.map +1 -0
  96. package/dist/frontend/page_catalog.cjs +135 -0
  97. package/dist/frontend/page_catalog.cjs.map +1 -0
  98. package/dist/frontend/page_catalog.d.cts +56 -0
  99. package/dist/frontend/page_catalog.d.ts +56 -0
  100. package/dist/frontend/page_catalog.js +108 -0
  101. package/dist/frontend/page_catalog.js.map +1 -0
  102. package/dist/frontend/tracked_transport.cjs +55 -0
  103. package/dist/frontend/tracked_transport.cjs.map +1 -0
  104. package/dist/frontend/tracked_transport.d.cts +36 -0
  105. package/dist/frontend/tracked_transport.d.ts +36 -0
  106. package/dist/frontend/tracked_transport.js +31 -0
  107. package/dist/frontend/tracked_transport.js.map +1 -0
  108. package/dist/frontend/work_registry.cjs +153 -0
  109. package/dist/frontend/work_registry.cjs.map +1 -0
  110. package/dist/frontend/work_registry.d.cts +70 -0
  111. package/dist/frontend/work_registry.d.ts +70 -0
  112. package/dist/frontend/work_registry.js +128 -0
  113. package/dist/frontend/work_registry.js.map +1 -0
  114. package/dist/index.cjs +24 -0
  115. package/dist/index.cjs.map +1 -1
  116. package/dist/index.d.cts +10 -7
  117. package/dist/index.d.ts +10 -7
  118. package/dist/index.js +27 -4
  119. package/dist/index.js.map +1 -1
  120. package/dist/main/index.cjs +10 -0
  121. package/dist/main/index.cjs.map +1 -1
  122. package/dist/main/index.d.cts +14 -2
  123. package/dist/main/index.d.ts +14 -2
  124. package/dist/main/index.js +16 -0
  125. package/dist/main/index.js.map +1 -1
  126. package/dist/middleware/middleware_resolver.cjs +22 -1
  127. package/dist/middleware/middleware_resolver.cjs.map +1 -1
  128. package/dist/middleware/middleware_resolver.d.cts +13 -1
  129. package/dist/middleware/middleware_resolver.d.ts +13 -1
  130. package/dist/middleware/middleware_resolver.js +22 -1
  131. package/dist/middleware/middleware_resolver.js.map +1 -1
  132. package/dist/navigation/index.cjs +3 -0
  133. package/dist/navigation/index.cjs.map +1 -1
  134. package/dist/navigation/index.d.cts +25 -1
  135. package/dist/navigation/index.d.ts +25 -1
  136. package/dist/navigation/index.js +2 -0
  137. package/dist/navigation/index.js.map +1 -1
  138. package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
  139. package/dist/navigation/layout_preservation.cjs.map +1 -0
  140. package/dist/navigation/layout_preservation.d.cts +2 -0
  141. package/dist/navigation/layout_preservation.d.ts +2 -0
  142. package/dist/navigation/layout_preservation.js +18 -0
  143. package/dist/navigation/layout_preservation.js.map +1 -0
  144. package/dist/parser/index.cjs +2 -0
  145. package/dist/parser/index.cjs.map +1 -1
  146. package/dist/parser/index.d.cts +1 -1
  147. package/dist/parser/index.d.ts +1 -1
  148. package/dist/parser/index.js +2 -1
  149. package/dist/parser/index.js.map +1 -1
  150. package/dist/parser/operations_parser.cjs +6 -0
  151. package/dist/parser/operations_parser.cjs.map +1 -1
  152. package/dist/parser/operations_parser.d.cts +9 -2
  153. package/dist/parser/operations_parser.d.ts +9 -2
  154. package/dist/parser/operations_parser.js +5 -0
  155. package/dist/parser/operations_parser.js.map +1 -1
  156. package/dist/parser/views_parser.cjs.map +1 -1
  157. package/dist/parser/views_parser.js.map +1 -1
  158. package/dist/router/index.d.cts +1 -0
  159. package/dist/router/index.d.ts +1 -0
  160. package/dist/router/wood_router.cjs +35 -3
  161. package/dist/router/wood_router.cjs.map +1 -1
  162. package/dist/router/wood_router.d.cts +15 -0
  163. package/dist/router/wood_router.d.ts +15 -0
  164. package/dist/router/wood_router.js +36 -4
  165. package/dist/router/wood_router.js.map +1 -1
  166. package/dist/runtime/get_container.cjs +9 -34
  167. package/dist/runtime/get_container.cjs.map +1 -1
  168. package/dist/runtime/get_container.d.cts +24 -4
  169. package/dist/runtime/get_container.d.ts +24 -4
  170. package/dist/runtime/get_container.js +8 -23
  171. package/dist/runtime/get_container.js.map +1 -1
  172. package/dist/runtime/index.cjs +9 -0
  173. package/dist/runtime/index.cjs.map +1 -1
  174. package/dist/runtime/index.d.cts +5 -2
  175. package/dist/runtime/index.d.ts +5 -2
  176. package/dist/runtime/index.js +10 -1
  177. package/dist/runtime/index.js.map +1 -1
  178. package/dist/runtime/renderer_config_extension.cjs +50 -0
  179. package/dist/runtime/renderer_config_extension.cjs.map +1 -0
  180. package/dist/runtime/renderer_config_extension.d.cts +19 -0
  181. package/dist/runtime/renderer_config_extension.d.ts +19 -0
  182. package/dist/runtime/renderer_config_extension.js +24 -0
  183. package/dist/runtime/renderer_config_extension.js.map +1 -0
  184. package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
  185. package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
  186. package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
  187. package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
  188. package/dist/runtime/renderer_log_batch_receiver.js +48 -0
  189. package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
  190. package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
  191. package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
  192. package/dist/runtime/runtime.cjs +14 -0
  193. package/dist/runtime/runtime.cjs.map +1 -1
  194. package/dist/runtime/runtime.d.cts +2 -1
  195. package/dist/runtime/runtime.d.ts +2 -1
  196. package/dist/runtime/runtime.js +14 -0
  197. package/dist/runtime/runtime.js.map +1 -1
  198. package/dist/stick/index.cjs.map +1 -1
  199. package/dist/stick/index.js.map +1 -1
  200. package/dist/testing/browser.cjs +104 -23
  201. package/dist/testing/browser.cjs.map +1 -1
  202. package/dist/testing/browser.d.cts +8 -3
  203. package/dist/testing/browser.d.ts +8 -3
  204. package/dist/testing/browser.js +102 -22
  205. package/dist/testing/browser.js.map +1 -1
  206. package/dist/testing/create_controller_harness.cjs +28 -8
  207. package/dist/testing/create_controller_harness.cjs.map +1 -1
  208. package/dist/testing/create_controller_harness.d.cts +17 -2
  209. package/dist/testing/create_controller_harness.d.ts +17 -2
  210. package/dist/testing/create_controller_harness.js +28 -8
  211. package/dist/testing/create_controller_harness.js.map +1 -1
  212. package/dist/testing/create_router_bridge.d.cts +1 -0
  213. package/dist/testing/create_router_bridge.d.ts +1 -0
  214. package/dist/testing/create_test_router.d.cts +1 -0
  215. package/dist/testing/create_test_router.d.ts +1 -0
  216. package/dist/testing/index.cjs +31 -0
  217. package/dist/testing/index.cjs.map +1 -1
  218. package/dist/testing/index.d.cts +20 -5
  219. package/dist/testing/index.d.ts +20 -5
  220. package/dist/testing/index.js +19 -1
  221. package/dist/testing/index.js.map +1 -1
  222. package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
  223. package/dist/testing/test_wood.cjs.map +1 -0
  224. package/dist/testing/test_wood.d.cts +16 -0
  225. package/dist/testing/test_wood.d.ts +16 -0
  226. package/dist/testing/test_wood.js +12 -0
  227. package/dist/testing/test_wood.js.map +1 -0
  228. package/dist/testing/test_wood_config.cjs +272 -0
  229. package/dist/testing/test_wood_config.cjs.map +1 -0
  230. package/dist/testing/test_wood_config.d.cts +111 -0
  231. package/dist/testing/test_wood_config.d.ts +111 -0
  232. package/dist/testing/test_wood_config.js +247 -0
  233. package/dist/testing/test_wood_config.js.map +1 -0
  234. package/dist/testing/wood_config_source.cjs +146 -0
  235. package/dist/testing/wood_config_source.cjs.map +1 -0
  236. package/dist/testing/wood_config_source.d.cts +36 -0
  237. package/dist/testing/wood_config_source.d.ts +36 -0
  238. package/dist/testing/wood_config_source.js +112 -0
  239. package/dist/testing/wood_config_source.js.map +1 -0
  240. package/dist/testing/wood_env_renderer.cjs +210 -0
  241. package/dist/testing/wood_env_renderer.cjs.map +1 -0
  242. package/dist/testing/wood_env_renderer.d.cts +74 -0
  243. package/dist/testing/wood_env_renderer.d.ts +74 -0
  244. package/dist/testing/wood_env_renderer.js +188 -0
  245. package/dist/testing/wood_env_renderer.js.map +1 -0
  246. package/dist/testing/wood_test_selection.cjs +94 -0
  247. package/dist/testing/wood_test_selection.cjs.map +1 -0
  248. package/dist/testing/wood_test_selection.d.cts +39 -0
  249. package/dist/testing/wood_test_selection.d.ts +39 -0
  250. package/dist/testing/wood_test_selection.js +68 -0
  251. package/dist/testing/wood_test_selection.js.map +1 -0
  252. package/dist/trace-testing/index.d.cts +1 -2
  253. package/dist/trace-testing/index.d.ts +1 -2
  254. package/dist/trace-testing/trace_recorder.cjs +1 -1
  255. package/dist/trace-testing/trace_recorder.cjs.map +1 -1
  256. package/dist/trace-testing/trace_recorder.d.cts +1 -2
  257. package/dist/trace-testing/trace_recorder.d.ts +1 -2
  258. package/dist/trace-testing/trace_recorder.js +1 -1
  259. package/dist/trace-testing/trace_recorder.js.map +1 -1
  260. package/dist/trace-transport/index.d.cts +1 -1
  261. package/dist/trace-transport/index.d.ts +1 -1
  262. package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
  263. package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
  264. package/dist/tracing/index.cjs +9 -2
  265. package/dist/tracing/index.cjs.map +1 -1
  266. package/dist/tracing/index.d.cts +3 -2
  267. package/dist/tracing/index.d.ts +3 -2
  268. package/dist/tracing/index.js +7 -1
  269. package/dist/tracing/index.js.map +1 -1
  270. package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
  271. package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
  272. package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
  273. package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
  274. package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
  275. package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
  276. package/dist/tracing/renderer_trace_batch_transport.js +48 -6
  277. package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
  278. package/dist/tracing/trace_batch_adapter.cjs +110 -0
  279. package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
  280. package/dist/tracing/trace_batch_adapter.d.cts +36 -0
  281. package/dist/tracing/trace_batch_adapter.d.ts +36 -0
  282. package/dist/tracing/trace_batch_adapter.js +86 -0
  283. package/dist/tracing/trace_batch_adapter.js.map +1 -0
  284. package/dist/tracing/trace_commit_writer.d.cts +1 -1
  285. package/dist/tracing/trace_commit_writer.d.ts +1 -1
  286. package/dist/tracing/trace_hub.cjs +87 -20
  287. package/dist/tracing/trace_hub.cjs.map +1 -1
  288. package/dist/tracing/trace_hub.d.cts +1 -1
  289. package/dist/tracing/trace_hub.d.ts +1 -1
  290. package/dist/tracing/trace_hub.js +85 -20
  291. package/dist/tracing/trace_hub.js.map +1 -1
  292. package/dist/tracing/trace_provider.cjs +21 -6
  293. package/dist/tracing/trace_provider.cjs.map +1 -1
  294. package/dist/tracing/trace_provider.d.cts +13 -4
  295. package/dist/tracing/trace_provider.d.ts +13 -4
  296. package/dist/tracing/trace_provider.js +22 -7
  297. package/dist/tracing/trace_provider.js.map +1 -1
  298. package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
  299. package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
  300. package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
  301. package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
  302. package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
  303. package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
  304. package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
  305. package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
  306. package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
  307. package/dist/tracing/wood_trace_batch_contract.js +2 -0
  308. package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
  309. package/dist/transport/build_transport_bridge.cjs +4 -2
  310. package/dist/transport/build_transport_bridge.cjs.map +1 -1
  311. package/dist/transport/build_transport_bridge.d.cts +7 -1
  312. package/dist/transport/build_transport_bridge.d.ts +7 -1
  313. package/dist/transport/build_transport_bridge.js +2 -1
  314. package/dist/transport/build_transport_bridge.js.map +1 -1
  315. package/dist/transport/in_process_router_transport.d.cts +1 -0
  316. package/dist/transport/in_process_router_transport.d.ts +1 -0
  317. package/dist/transport/index.d.cts +1 -0
  318. package/dist/transport/index.d.ts +1 -0
  319. package/dist/types/config.cjs.map +1 -1
  320. package/dist/types/config.d.cts +47 -1
  321. package/dist/types/config.d.ts +47 -1
  322. package/dist/types/context.cjs +12 -0
  323. package/dist/types/context.cjs.map +1 -1
  324. package/dist/types/context.d.cts +27 -1
  325. package/dist/types/context.d.ts +27 -1
  326. package/dist/types/context.js +4 -0
  327. package/dist/types/context.js.map +1 -1
  328. package/dist/types/index.d.cts +2 -2
  329. package/dist/types/index.d.ts +2 -2
  330. package/dist/types/operations.cjs.map +1 -1
  331. package/dist/types/operations.d.cts +2 -0
  332. package/dist/types/operations.d.ts +2 -0
  333. package/docs/axe.md +706 -0
  334. package/package.json +13 -5
  335. package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
  336. package/src/components/NavigationShell.svelte +126 -49
  337. package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
  338. package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
  339. package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
  340. package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
  341. package/dist/controller/__fixtures__/controllers/chat.js +0 -12
  342. package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
  343. package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
  344. package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
  345. package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
  346. package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
  347. package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
  348. package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
  349. package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
  350. package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
  351. package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
  352. package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
  353. package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
  354. package/dist/controller/__fixtures__/controllers/test.cjs +0 -29
  355. package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
  356. package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
  357. package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
  358. package/dist/controller/__fixtures__/controllers/test.js +0 -9
  359. package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
  360. package/dist/loader/__fixtures__/layouts/app.load.cjs +0 -27
  361. package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
  362. package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
  363. package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
  364. package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
  365. package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
  366. package/dist/loader/__fixtures__/views/test/page.load.cjs +0 -27
  367. package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
  368. package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
  369. package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
  370. package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
  371. package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
  372. package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
  373. package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
  374. package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
  375. package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
  376. package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
  377. package/dist/middleware/__fixtures__/middleware/sequence.cjs +0 -47
  378. package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
  379. package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
  380. package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
  381. package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
  382. package/dist/middleware/__fixtures__/middleware/sequence.js.map +0 -1
@@ -0,0 +1,50 @@
1
+ import { FrontendWorkError } from "./work_registry.js";
2
+ class FrontendLifecycleOwner {
3
+ constructor(registry, owner) {
4
+ this.registry = registry;
5
+ this.owner = owner;
6
+ this.abortController = new AbortController();
7
+ this.resources = [];
8
+ this.disposed = false;
9
+ }
10
+ get signal() {
11
+ return this.abortController.signal;
12
+ }
13
+ track(work, options) {
14
+ if (this.disposed) {
15
+ throw new FrontendWorkError(
16
+ `cannot track "${options.label}": lifecycle "${this.owner}" is disposed. Work started after a page/environment ended is a product lifecycle bug.`
17
+ );
18
+ }
19
+ return this.registry.track(work, {
20
+ label: options.label,
21
+ kind: options.kind ?? "tracked",
22
+ owner: this.owner
23
+ });
24
+ }
25
+ own(resource) {
26
+ if (this.disposed) {
27
+ throw new FrontendWorkError(
28
+ `cannot own a resource: lifecycle "${this.owner}" is disposed.`
29
+ );
30
+ }
31
+ this.resources.push(resource);
32
+ }
33
+ get isDisposed() {
34
+ return this.disposed;
35
+ }
36
+ /** Abort owned work and dispose owned resources in reverse order. */
37
+ async dispose() {
38
+ if (this.disposed) return;
39
+ this.disposed = true;
40
+ this.abortController.abort();
41
+ for (const resource of this.resources.reverse()) {
42
+ await resource.dispose();
43
+ }
44
+ this.resources.length = 0;
45
+ }
46
+ }
47
+ export {
48
+ FrontendLifecycleOwner
49
+ };
50
+ //# sourceMappingURL=frontend_lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/frontend/frontend_lifecycle.ts"],"sourcesContent":["/**\n * Production lifecycle owners for deliberately detached frontend work\n * (18A D-FAS-01 §2.2). Two natural owners exist per environment:\n *\n * page lifecycle — default for PageController work; aborted and\n * disposed when that page ends\n * application lifecycle — explicit for work that intentionally survives\n * page navigation; disposed with the environment\n *\n * PageControllers/client services register their own deliberately detached\n * finite work through their injected lifecycle owner — tests do not repair\n * unowned product code by wrapping it in track() from the outside.\n */\nimport { WorkRegistry, FrontendWorkError } from './work_registry.js';\n\nexport interface FrontendLifecycle {\n readonly signal: AbortSignal;\n\n track<T>(\n work: Promise<T>,\n options: {\n label: string;\n kind?: string;\n },\n ): Promise<T>;\n\n own(resource: { dispose(): void | Promise<void> }): void;\n}\n\nexport class FrontendLifecycleOwner implements FrontendLifecycle {\n private readonly abortController = new AbortController();\n private readonly resources: Array<{ dispose(): void | Promise<void> }> = [];\n private disposed = false;\n\n constructor(\n private readonly registry: WorkRegistry,\n /** Diagnostic owner identity, e.g. `page main.chat_dom` or `application`. */\n readonly owner: string,\n ) {}\n\n get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n track<T>(work: Promise<T>, options: { label: string; kind?: string }): Promise<T> {\n if (this.disposed) {\n throw new FrontendWorkError(\n `cannot track \"${options.label}\": lifecycle \"${this.owner}\" is disposed. ` +\n 'Work started after a page/environment ended is a product lifecycle bug.',\n );\n }\n return this.registry.track(work, {\n label: options.label,\n kind: options.kind ?? 'tracked',\n owner: this.owner,\n });\n }\n\n own(resource: { dispose(): void | Promise<void> }): void {\n if (this.disposed) {\n throw new FrontendWorkError(\n `cannot own a resource: lifecycle \"${this.owner}\" is disposed.`,\n );\n }\n this.resources.push(resource);\n }\n\n get isDisposed(): boolean {\n return this.disposed;\n }\n\n /** Abort owned work and dispose owned resources in reverse order. */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n this.abortController.abort();\n for (const resource of this.resources.reverse()) {\n await resource.dispose();\n }\n this.resources.length = 0;\n }\n}\n"],"mappings":"AAaA,SAAuB,yBAAyB;AAgBzC,MAAM,uBAAoD;AAAA,EAK/D,YACmB,UAER,OACT;AAHiB;AAER;AAPX,SAAiB,kBAAkB,IAAI,gBAAgB;AACvD,SAAiB,YAAwD,CAAC;AAC1E,SAAQ,WAAW;AAAA,EAMhB;AAAA,EAEH,IAAI,SAAsB;AACxB,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,MAAS,MAAkB,SAAuD;AAChF,QAAI,KAAK,UAAU;AACjB,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,KAAK,iBAAiB,KAAK,KAAK;AAAA,MAE3D;AAAA,IACF;AACA,WAAO,KAAK,SAAS,MAAM,MAAM;AAAA,MAC/B,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ,QAAQ;AAAA,MACtB,OAAO,KAAK;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,UAAqD;AACvD,QAAI,KAAK,UAAU;AACjB,YAAM,IAAI;AAAA,QACR,qCAAqC,KAAK,KAAK;AAAA,MACjD;AAAA,IACF;AACA,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAChB,SAAK,gBAAgB,MAAM;AAC3B,eAAW,YAAY,KAAK,UAAU,QAAQ,GAAG;AAC/C,YAAM,SAAS,QAAQ;AAAA,IACzB;AACA,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;","names":[]}
@@ -0,0 +1,122 @@
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 frontend_page_exports = {};
20
+ __export(frontend_page_exports, {
21
+ createFrontendPage: () => createFrontendPage
22
+ });
23
+ module.exports = __toCommonJS(frontend_page_exports);
24
+ var import_ioc = require("@noego/ioc");
25
+ var import_work_registry = require("./work_registry.js");
26
+ function bridgeSurface(surface, scope) {
27
+ if (!surface || typeof surface !== "object") return surface;
28
+ const wrapped = /* @__PURE__ */ new WeakMap();
29
+ return new Proxy(surface, {
30
+ get(target, property, receiver) {
31
+ const value = Reflect.get(target, property, receiver === void 0 ? target : target);
32
+ if (typeof value !== "function") return value;
33
+ const fn = value;
34
+ const cached = wrapped.get(fn);
35
+ if (cached) return cached;
36
+ const bridged = (...args) => import_ioc.ExecutionContext.current() !== void 0 ? fn.apply(target, args) : import_ioc.ExecutionContext.run(scope, () => fn.apply(target, args));
37
+ wrapped.set(fn, bridged);
38
+ return bridged;
39
+ }
40
+ });
41
+ }
42
+ function createFrontendPage(options) {
43
+ const { identity, controller, scope } = options;
44
+ let closed = false;
45
+ const bridgedInput = bridgeSurface(controller.input, scope);
46
+ const bridgedEvents = bridgeSurface(controller.events, scope);
47
+ const layouts = (options.layouts ?? []).map((mounted) => {
48
+ const layoutInput = bridgeSurface(mounted.instance.input, mounted.scope);
49
+ const layoutEvents = bridgeSurface(mounted.instance.events, mounted.scope);
50
+ return {
51
+ path: mounted.path,
52
+ controller: mounted.controller,
53
+ preserve: mounted.preserve,
54
+ get data() {
55
+ guard();
56
+ return mounted.instance.data;
57
+ },
58
+ get input() {
59
+ guard();
60
+ return layoutInput;
61
+ },
62
+ get events() {
63
+ guard();
64
+ return layoutEvents;
65
+ }
66
+ };
67
+ });
68
+ const guard = () => {
69
+ if (closed) {
70
+ throw new import_work_registry.FrontendWorkError(
71
+ `page "${identity}" is closed; a closed/navigated-away page handle must not be used. Re-open the page or use frontend.current().`
72
+ );
73
+ }
74
+ };
75
+ const page = {
76
+ identity,
77
+ get data() {
78
+ guard();
79
+ return controller.data;
80
+ },
81
+ get input() {
82
+ guard();
83
+ return bridgedInput;
84
+ },
85
+ get events() {
86
+ guard();
87
+ return bridgedEvents;
88
+ },
89
+ get layouts() {
90
+ guard();
91
+ return layouts;
92
+ },
93
+ get layout() {
94
+ guard();
95
+ if (layouts.length === 1) return layouts[0];
96
+ if (!layouts.length) {
97
+ throw new import_work_registry.FrontendWorkError(
98
+ `page "${identity}" mounts no layout controller; its views entry binds none.`
99
+ );
100
+ }
101
+ throw new import_work_registry.FrontendWorkError(
102
+ `page "${identity}" mounts ${layouts.length} layout controllers (${layouts.map((entry) => entry.controller).join(", ")}); use page.layouts and name the one you mean.`
103
+ );
104
+ },
105
+ close: async () => {
106
+ if (closed) return;
107
+ closed = true;
108
+ await options.onClose();
109
+ }
110
+ };
111
+ return {
112
+ page,
113
+ invalidate: () => {
114
+ closed = true;
115
+ }
116
+ };
117
+ }
118
+ // Annotate the CommonJS export names for ESM import in node:
119
+ 0 && (module.exports = {
120
+ createFrontendPage
121
+ });
122
+ //# sourceMappingURL=frontend_page.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/frontend/frontend_page.ts"],"sourcesContent":["/**\n * The public frontend page projection (18A D-FAS-05).\n *\n * `FrontendPage` exposes the production `data / input / events` contract of\n * the selected PageController — never the controller instance itself, never\n * private or IoC-only members. References are not cloned (reactivity is\n * preserved); `input`/`events` handlers are bridged so they execute under\n * the page scope's IoC execution context, exactly as the production\n * renderer runtime invokes them (they are plain data properties holding\n * arrow functions, which would otherwise run context-less from a test).\n */\nimport { ExecutionContext } from '@noego/ioc';\nimport { FrontendWorkError } from './work_registry.js';\n\n/**\n * The public projection of one mounted LAYOUT controller (18A D-FAS-05).\n *\n * Layout controllers are production page members — the views YAML binds\n * them, the renderer mounts them alongside the view controller, and a\n * `preserve: true` layout outlives page transitions. They therefore expose\n * the same public `data / input / events` contract as the page controller,\n * never their instance.\n */\nexport interface FrontendLayout<Data = unknown, Input = unknown, Events = unknown> {\n /** The layout view path as declared in the views source. */\n readonly path: string;\n /** The layout controller identity as declared in the views source. */\n readonly controller: string;\n /** Whether the views source declares this layout preservable. */\n readonly preserve: boolean;\n readonly data: Data;\n readonly input: Input;\n readonly events: Events | undefined;\n}\n\nexport interface FrontendPage<Data = unknown, Input = unknown, Events = unknown> {\n /** Canonical `window.page` production identity. */\n readonly identity: string;\n readonly data: Data;\n readonly input: Input;\n readonly events: Events | undefined;\n /** Every mounted layout controller of this page, outermost first. */\n readonly layouts: readonly FrontendLayout[];\n /**\n * The page's sole layout controller. Throws when the page declares none,\n * or more than one — use `layouts` and name the layout explicitly there.\n */\n readonly layout: FrontendLayout;\n close(): Promise<void>;\n}\n\ninterface PageControllerLike {\n data?: unknown;\n input?: unknown;\n events?: unknown;\n}\n\nfunction bridgeSurface(surface: unknown, scope: unknown): unknown {\n if (!surface || typeof surface !== 'object') return surface;\n // Proxy, not a copy: input/events surfaces are often class instances\n // (methods on the prototype) or reactive objects (accessor-backed state);\n // a proxy preserves both while wrapping function reads so handlers run\n // under the page scope's execution context.\n const wrapped = new WeakMap<object, unknown>();\n return new Proxy(surface as object, {\n get(target, property, receiver) {\n const value = Reflect.get(target, property, receiver === undefined ? target : target);\n if (typeof value !== 'function') return value;\n const fn = value as (...args: unknown[]) => unknown;\n const cached = wrapped.get(fn);\n if (cached) return cached;\n const bridged = (...args: unknown[]) =>\n ExecutionContext.current() !== undefined\n ? fn.apply(target, args)\n : ExecutionContext.run(scope as never, () => fn.apply(target, args));\n wrapped.set(fn, bridged);\n return bridged;\n },\n });\n}\n\nexport interface FrontendPageHandle<Data = unknown, Input = unknown, Events = unknown> {\n page: FrontendPage<Data, Input, Events>;\n /** Mark the projection stale without disposing (navigation already disposed the scope). */\n invalidate: () => void;\n}\n\n/** One mounted layout controller with the scope its handlers run under. */\nexport interface MountedLayout {\n path: string;\n controller: string;\n preserve: boolean;\n instance: PageControllerLike;\n scope: unknown;\n}\n\nexport function createFrontendPage<Data, Input, Events>(options: {\n identity: string;\n controller: PageControllerLike;\n scope: unknown;\n layouts?: readonly MountedLayout[];\n onClose: () => Promise<void>;\n}): FrontendPageHandle<Data, Input, Events> {\n const { identity, controller, scope } = options;\n let closed = false;\n\n const bridgedInput = bridgeSurface(controller.input, scope);\n const bridgedEvents = bridgeSurface(controller.events, scope);\n\n const layouts: FrontendLayout[] = (options.layouts ?? []).map((mounted) => {\n const layoutInput = bridgeSurface(mounted.instance.input, mounted.scope);\n const layoutEvents = bridgeSurface(mounted.instance.events, mounted.scope);\n return {\n path: mounted.path,\n controller: mounted.controller,\n preserve: mounted.preserve,\n get data() {\n guard();\n return mounted.instance.data;\n },\n get input() {\n guard();\n return layoutInput;\n },\n get events() {\n guard();\n return layoutEvents;\n },\n };\n });\n\n const guard = (): void => {\n if (closed) {\n throw new FrontendWorkError(\n `page \"${identity}\" is closed; a closed/navigated-away page handle must not be used. ` +\n 'Re-open the page or use frontend.current().',\n );\n }\n };\n\n const page: FrontendPage<Data, Input, Events> = {\n identity,\n get data(): Data {\n guard();\n return controller.data as Data;\n },\n get input(): Input {\n guard();\n return bridgedInput as Input;\n },\n get events(): Events | undefined {\n guard();\n return bridgedEvents as Events | undefined;\n },\n get layouts(): readonly FrontendLayout[] {\n guard();\n return layouts;\n },\n get layout(): FrontendLayout {\n guard();\n if (layouts.length === 1) return layouts[0];\n if (!layouts.length) {\n throw new FrontendWorkError(\n `page \"${identity}\" mounts no layout controller; its views entry binds none.`,\n );\n }\n throw new FrontendWorkError(\n `page \"${identity}\" mounts ${layouts.length} layout controllers ` +\n `(${layouts.map((entry) => entry.controller).join(', ')}); ` +\n 'use page.layouts and name the one you mean.',\n );\n },\n close: async () => {\n if (closed) return;\n closed = true;\n await options.onClose();\n },\n };\n\n return {\n page,\n invalidate: () => {\n closed = true;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,iBAAiC;AACjC,2BAAkC;AA6ClC,SAAS,cAAc,SAAkB,OAAyB;AAChE,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AAKpD,QAAM,UAAU,oBAAI,QAAyB;AAC7C,SAAO,IAAI,MAAM,SAAmB;AAAA,IAClC,IAAI,QAAQ,UAAU,UAAU;AAC9B,YAAM,QAAQ,QAAQ,IAAI,QAAQ,UAAU,aAAa,SAAY,SAAS,MAAM;AACpF,UAAI,OAAO,UAAU,WAAY,QAAO;AACxC,YAAM,KAAK;AACX,YAAM,SAAS,QAAQ,IAAI,EAAE;AAC7B,UAAI,OAAQ,QAAO;AACnB,YAAM,UAAU,IAAI,SAClB,4BAAiB,QAAQ,MAAM,SAC3B,GAAG,MAAM,QAAQ,IAAI,IACrB,4BAAiB,IAAI,OAAgB,MAAM,GAAG,MAAM,QAAQ,IAAI,CAAC;AACvE,cAAQ,IAAI,IAAI,OAAO;AACvB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAiBO,SAAS,mBAAwC,SAMZ;AAC1C,QAAM,EAAE,UAAU,YAAY,MAAM,IAAI;AACxC,MAAI,SAAS;AAEb,QAAM,eAAe,cAAc,WAAW,OAAO,KAAK;AAC1D,QAAM,gBAAgB,cAAc,WAAW,QAAQ,KAAK;AAE5D,QAAM,WAA6B,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,YAAY;AACzE,UAAM,cAAc,cAAc,QAAQ,SAAS,OAAO,QAAQ,KAAK;AACvE,UAAM,eAAe,cAAc,QAAQ,SAAS,QAAQ,QAAQ,KAAK;AACzE,WAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,IAAI,OAAO;AACT,cAAM;AACN,eAAO,QAAQ,SAAS;AAAA,MAC1B;AAAA,MACA,IAAI,QAAQ;AACV,cAAM;AACN,eAAO;AAAA,MACT;AAAA,MACA,IAAI,SAAS;AACX,cAAM;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,MAAY;AACxB,QAAI,QAAQ;AACV,YAAM,IAAI;AAAA,QACR,SAAS,QAAQ;AAAA,MAEnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAA0C;AAAA,IAC9C;AAAA,IACA,IAAI,OAAa;AACf,YAAM;AACN,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,IAAI,QAAe;AACjB,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,SAA6B;AAC/B,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,UAAqC;AACvC,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,SAAyB;AAC3B,YAAM;AACN,UAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ,CAAC;AAC1C,UAAI,CAAC,QAAQ,QAAQ;AACnB,cAAM,IAAI;AAAA,UACR,SAAS,QAAQ;AAAA,QACnB;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,SAAS,QAAQ,YAAY,QAAQ,MAAM,wBACvC,QAAQ,IAAI,CAAC,UAAU,MAAM,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,MAEzD;AAAA,IACF;AAAA,IACA,OAAO,YAAY;AACjB,UAAI,OAAQ;AACZ,eAAS;AACT,YAAM,QAAQ,QAAQ;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAY,MAAM;AAChB,eAAS;AAAA,IACX;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The public projection of one mounted LAYOUT controller (18A D-FAS-05).
3
+ *
4
+ * Layout controllers are production page members — the views YAML binds
5
+ * them, the renderer mounts them alongside the view controller, and a
6
+ * `preserve: true` layout outlives page transitions. They therefore expose
7
+ * the same public `data / input / events` contract as the page controller,
8
+ * never their instance.
9
+ */
10
+ interface FrontendLayout<Data = unknown, Input = unknown, Events = unknown> {
11
+ /** The layout view path as declared in the views source. */
12
+ readonly path: string;
13
+ /** The layout controller identity as declared in the views source. */
14
+ readonly controller: string;
15
+ /** Whether the views source declares this layout preservable. */
16
+ readonly preserve: boolean;
17
+ readonly data: Data;
18
+ readonly input: Input;
19
+ readonly events: Events | undefined;
20
+ }
21
+ interface FrontendPage<Data = unknown, Input = unknown, Events = unknown> {
22
+ /** Canonical `window.page` production identity. */
23
+ readonly identity: string;
24
+ readonly data: Data;
25
+ readonly input: Input;
26
+ readonly events: Events | undefined;
27
+ /** Every mounted layout controller of this page, outermost first. */
28
+ readonly layouts: readonly FrontendLayout[];
29
+ /**
30
+ * The page's sole layout controller. Throws when the page declares none,
31
+ * or more than one — use `layouts` and name the layout explicitly there.
32
+ */
33
+ readonly layout: FrontendLayout;
34
+ close(): Promise<void>;
35
+ }
36
+ interface PageControllerLike {
37
+ data?: unknown;
38
+ input?: unknown;
39
+ events?: unknown;
40
+ }
41
+ interface FrontendPageHandle<Data = unknown, Input = unknown, Events = unknown> {
42
+ page: FrontendPage<Data, Input, Events>;
43
+ /** Mark the projection stale without disposing (navigation already disposed the scope). */
44
+ invalidate: () => void;
45
+ }
46
+ /** One mounted layout controller with the scope its handlers run under. */
47
+ interface MountedLayout {
48
+ path: string;
49
+ controller: string;
50
+ preserve: boolean;
51
+ instance: PageControllerLike;
52
+ scope: unknown;
53
+ }
54
+ declare function createFrontendPage<Data, Input, Events>(options: {
55
+ identity: string;
56
+ controller: PageControllerLike;
57
+ scope: unknown;
58
+ layouts?: readonly MountedLayout[];
59
+ onClose: () => Promise<void>;
60
+ }): FrontendPageHandle<Data, Input, Events>;
61
+
62
+ export { type FrontendLayout, type FrontendPage, type FrontendPageHandle, type MountedLayout, createFrontendPage };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The public projection of one mounted LAYOUT controller (18A D-FAS-05).
3
+ *
4
+ * Layout controllers are production page members — the views YAML binds
5
+ * them, the renderer mounts them alongside the view controller, and a
6
+ * `preserve: true` layout outlives page transitions. They therefore expose
7
+ * the same public `data / input / events` contract as the page controller,
8
+ * never their instance.
9
+ */
10
+ interface FrontendLayout<Data = unknown, Input = unknown, Events = unknown> {
11
+ /** The layout view path as declared in the views source. */
12
+ readonly path: string;
13
+ /** The layout controller identity as declared in the views source. */
14
+ readonly controller: string;
15
+ /** Whether the views source declares this layout preservable. */
16
+ readonly preserve: boolean;
17
+ readonly data: Data;
18
+ readonly input: Input;
19
+ readonly events: Events | undefined;
20
+ }
21
+ interface FrontendPage<Data = unknown, Input = unknown, Events = unknown> {
22
+ /** Canonical `window.page` production identity. */
23
+ readonly identity: string;
24
+ readonly data: Data;
25
+ readonly input: Input;
26
+ readonly events: Events | undefined;
27
+ /** Every mounted layout controller of this page, outermost first. */
28
+ readonly layouts: readonly FrontendLayout[];
29
+ /**
30
+ * The page's sole layout controller. Throws when the page declares none,
31
+ * or more than one — use `layouts` and name the layout explicitly there.
32
+ */
33
+ readonly layout: FrontendLayout;
34
+ close(): Promise<void>;
35
+ }
36
+ interface PageControllerLike {
37
+ data?: unknown;
38
+ input?: unknown;
39
+ events?: unknown;
40
+ }
41
+ interface FrontendPageHandle<Data = unknown, Input = unknown, Events = unknown> {
42
+ page: FrontendPage<Data, Input, Events>;
43
+ /** Mark the projection stale without disposing (navigation already disposed the scope). */
44
+ invalidate: () => void;
45
+ }
46
+ /** One mounted layout controller with the scope its handlers run under. */
47
+ interface MountedLayout {
48
+ path: string;
49
+ controller: string;
50
+ preserve: boolean;
51
+ instance: PageControllerLike;
52
+ scope: unknown;
53
+ }
54
+ declare function createFrontendPage<Data, Input, Events>(options: {
55
+ identity: string;
56
+ controller: PageControllerLike;
57
+ scope: unknown;
58
+ layouts?: readonly MountedLayout[];
59
+ onClose: () => Promise<void>;
60
+ }): FrontendPageHandle<Data, Input, Events>;
61
+
62
+ export { type FrontendLayout, type FrontendPage, type FrontendPageHandle, type MountedLayout, createFrontendPage };
@@ -0,0 +1,98 @@
1
+ import { ExecutionContext } from "@noego/ioc";
2
+ import { FrontendWorkError } from "./work_registry.js";
3
+ function bridgeSurface(surface, scope) {
4
+ if (!surface || typeof surface !== "object") return surface;
5
+ const wrapped = /* @__PURE__ */ new WeakMap();
6
+ return new Proxy(surface, {
7
+ get(target, property, receiver) {
8
+ const value = Reflect.get(target, property, receiver === void 0 ? target : target);
9
+ if (typeof value !== "function") return value;
10
+ const fn = value;
11
+ const cached = wrapped.get(fn);
12
+ if (cached) return cached;
13
+ const bridged = (...args) => ExecutionContext.current() !== void 0 ? fn.apply(target, args) : ExecutionContext.run(scope, () => fn.apply(target, args));
14
+ wrapped.set(fn, bridged);
15
+ return bridged;
16
+ }
17
+ });
18
+ }
19
+ function createFrontendPage(options) {
20
+ const { identity, controller, scope } = options;
21
+ let closed = false;
22
+ const bridgedInput = bridgeSurface(controller.input, scope);
23
+ const bridgedEvents = bridgeSurface(controller.events, scope);
24
+ const layouts = (options.layouts ?? []).map((mounted) => {
25
+ const layoutInput = bridgeSurface(mounted.instance.input, mounted.scope);
26
+ const layoutEvents = bridgeSurface(mounted.instance.events, mounted.scope);
27
+ return {
28
+ path: mounted.path,
29
+ controller: mounted.controller,
30
+ preserve: mounted.preserve,
31
+ get data() {
32
+ guard();
33
+ return mounted.instance.data;
34
+ },
35
+ get input() {
36
+ guard();
37
+ return layoutInput;
38
+ },
39
+ get events() {
40
+ guard();
41
+ return layoutEvents;
42
+ }
43
+ };
44
+ });
45
+ const guard = () => {
46
+ if (closed) {
47
+ throw new FrontendWorkError(
48
+ `page "${identity}" is closed; a closed/navigated-away page handle must not be used. Re-open the page or use frontend.current().`
49
+ );
50
+ }
51
+ };
52
+ const page = {
53
+ identity,
54
+ get data() {
55
+ guard();
56
+ return controller.data;
57
+ },
58
+ get input() {
59
+ guard();
60
+ return bridgedInput;
61
+ },
62
+ get events() {
63
+ guard();
64
+ return bridgedEvents;
65
+ },
66
+ get layouts() {
67
+ guard();
68
+ return layouts;
69
+ },
70
+ get layout() {
71
+ guard();
72
+ if (layouts.length === 1) return layouts[0];
73
+ if (!layouts.length) {
74
+ throw new FrontendWorkError(
75
+ `page "${identity}" mounts no layout controller; its views entry binds none.`
76
+ );
77
+ }
78
+ throw new FrontendWorkError(
79
+ `page "${identity}" mounts ${layouts.length} layout controllers (${layouts.map((entry) => entry.controller).join(", ")}); use page.layouts and name the one you mean.`
80
+ );
81
+ },
82
+ close: async () => {
83
+ if (closed) return;
84
+ closed = true;
85
+ await options.onClose();
86
+ }
87
+ };
88
+ return {
89
+ page,
90
+ invalidate: () => {
91
+ closed = true;
92
+ }
93
+ };
94
+ }
95
+ export {
96
+ createFrontendPage
97
+ };
98
+ //# sourceMappingURL=frontend_page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/frontend/frontend_page.ts"],"sourcesContent":["/**\n * The public frontend page projection (18A D-FAS-05).\n *\n * `FrontendPage` exposes the production `data / input / events` contract of\n * the selected PageController — never the controller instance itself, never\n * private or IoC-only members. References are not cloned (reactivity is\n * preserved); `input`/`events` handlers are bridged so they execute under\n * the page scope's IoC execution context, exactly as the production\n * renderer runtime invokes them (they are plain data properties holding\n * arrow functions, which would otherwise run context-less from a test).\n */\nimport { ExecutionContext } from '@noego/ioc';\nimport { FrontendWorkError } from './work_registry.js';\n\n/**\n * The public projection of one mounted LAYOUT controller (18A D-FAS-05).\n *\n * Layout controllers are production page members — the views YAML binds\n * them, the renderer mounts them alongside the view controller, and a\n * `preserve: true` layout outlives page transitions. They therefore expose\n * the same public `data / input / events` contract as the page controller,\n * never their instance.\n */\nexport interface FrontendLayout<Data = unknown, Input = unknown, Events = unknown> {\n /** The layout view path as declared in the views source. */\n readonly path: string;\n /** The layout controller identity as declared in the views source. */\n readonly controller: string;\n /** Whether the views source declares this layout preservable. */\n readonly preserve: boolean;\n readonly data: Data;\n readonly input: Input;\n readonly events: Events | undefined;\n}\n\nexport interface FrontendPage<Data = unknown, Input = unknown, Events = unknown> {\n /** Canonical `window.page` production identity. */\n readonly identity: string;\n readonly data: Data;\n readonly input: Input;\n readonly events: Events | undefined;\n /** Every mounted layout controller of this page, outermost first. */\n readonly layouts: readonly FrontendLayout[];\n /**\n * The page's sole layout controller. Throws when the page declares none,\n * or more than one — use `layouts` and name the layout explicitly there.\n */\n readonly layout: FrontendLayout;\n close(): Promise<void>;\n}\n\ninterface PageControllerLike {\n data?: unknown;\n input?: unknown;\n events?: unknown;\n}\n\nfunction bridgeSurface(surface: unknown, scope: unknown): unknown {\n if (!surface || typeof surface !== 'object') return surface;\n // Proxy, not a copy: input/events surfaces are often class instances\n // (methods on the prototype) or reactive objects (accessor-backed state);\n // a proxy preserves both while wrapping function reads so handlers run\n // under the page scope's execution context.\n const wrapped = new WeakMap<object, unknown>();\n return new Proxy(surface as object, {\n get(target, property, receiver) {\n const value = Reflect.get(target, property, receiver === undefined ? target : target);\n if (typeof value !== 'function') return value;\n const fn = value as (...args: unknown[]) => unknown;\n const cached = wrapped.get(fn);\n if (cached) return cached;\n const bridged = (...args: unknown[]) =>\n ExecutionContext.current() !== undefined\n ? fn.apply(target, args)\n : ExecutionContext.run(scope as never, () => fn.apply(target, args));\n wrapped.set(fn, bridged);\n return bridged;\n },\n });\n}\n\nexport interface FrontendPageHandle<Data = unknown, Input = unknown, Events = unknown> {\n page: FrontendPage<Data, Input, Events>;\n /** Mark the projection stale without disposing (navigation already disposed the scope). */\n invalidate: () => void;\n}\n\n/** One mounted layout controller with the scope its handlers run under. */\nexport interface MountedLayout {\n path: string;\n controller: string;\n preserve: boolean;\n instance: PageControllerLike;\n scope: unknown;\n}\n\nexport function createFrontendPage<Data, Input, Events>(options: {\n identity: string;\n controller: PageControllerLike;\n scope: unknown;\n layouts?: readonly MountedLayout[];\n onClose: () => Promise<void>;\n}): FrontendPageHandle<Data, Input, Events> {\n const { identity, controller, scope } = options;\n let closed = false;\n\n const bridgedInput = bridgeSurface(controller.input, scope);\n const bridgedEvents = bridgeSurface(controller.events, scope);\n\n const layouts: FrontendLayout[] = (options.layouts ?? []).map((mounted) => {\n const layoutInput = bridgeSurface(mounted.instance.input, mounted.scope);\n const layoutEvents = bridgeSurface(mounted.instance.events, mounted.scope);\n return {\n path: mounted.path,\n controller: mounted.controller,\n preserve: mounted.preserve,\n get data() {\n guard();\n return mounted.instance.data;\n },\n get input() {\n guard();\n return layoutInput;\n },\n get events() {\n guard();\n return layoutEvents;\n },\n };\n });\n\n const guard = (): void => {\n if (closed) {\n throw new FrontendWorkError(\n `page \"${identity}\" is closed; a closed/navigated-away page handle must not be used. ` +\n 'Re-open the page or use frontend.current().',\n );\n }\n };\n\n const page: FrontendPage<Data, Input, Events> = {\n identity,\n get data(): Data {\n guard();\n return controller.data as Data;\n },\n get input(): Input {\n guard();\n return bridgedInput as Input;\n },\n get events(): Events | undefined {\n guard();\n return bridgedEvents as Events | undefined;\n },\n get layouts(): readonly FrontendLayout[] {\n guard();\n return layouts;\n },\n get layout(): FrontendLayout {\n guard();\n if (layouts.length === 1) return layouts[0];\n if (!layouts.length) {\n throw new FrontendWorkError(\n `page \"${identity}\" mounts no layout controller; its views entry binds none.`,\n );\n }\n throw new FrontendWorkError(\n `page \"${identity}\" mounts ${layouts.length} layout controllers ` +\n `(${layouts.map((entry) => entry.controller).join(', ')}); ` +\n 'use page.layouts and name the one you mean.',\n );\n },\n close: async () => {\n if (closed) return;\n closed = true;\n await options.onClose();\n },\n };\n\n return {\n page,\n invalidate: () => {\n closed = true;\n },\n };\n}\n"],"mappings":"AAWA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AA6ClC,SAAS,cAAc,SAAkB,OAAyB;AAChE,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AAKpD,QAAM,UAAU,oBAAI,QAAyB;AAC7C,SAAO,IAAI,MAAM,SAAmB;AAAA,IAClC,IAAI,QAAQ,UAAU,UAAU;AAC9B,YAAM,QAAQ,QAAQ,IAAI,QAAQ,UAAU,aAAa,SAAY,SAAS,MAAM;AACpF,UAAI,OAAO,UAAU,WAAY,QAAO;AACxC,YAAM,KAAK;AACX,YAAM,SAAS,QAAQ,IAAI,EAAE;AAC7B,UAAI,OAAQ,QAAO;AACnB,YAAM,UAAU,IAAI,SAClB,iBAAiB,QAAQ,MAAM,SAC3B,GAAG,MAAM,QAAQ,IAAI,IACrB,iBAAiB,IAAI,OAAgB,MAAM,GAAG,MAAM,QAAQ,IAAI,CAAC;AACvE,cAAQ,IAAI,IAAI,OAAO;AACvB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAiBO,SAAS,mBAAwC,SAMZ;AAC1C,QAAM,EAAE,UAAU,YAAY,MAAM,IAAI;AACxC,MAAI,SAAS;AAEb,QAAM,eAAe,cAAc,WAAW,OAAO,KAAK;AAC1D,QAAM,gBAAgB,cAAc,WAAW,QAAQ,KAAK;AAE5D,QAAM,WAA6B,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,YAAY;AACzE,UAAM,cAAc,cAAc,QAAQ,SAAS,OAAO,QAAQ,KAAK;AACvE,UAAM,eAAe,cAAc,QAAQ,SAAS,QAAQ,QAAQ,KAAK;AACzE,WAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,IAAI,OAAO;AACT,cAAM;AACN,eAAO,QAAQ,SAAS;AAAA,MAC1B;AAAA,MACA,IAAI,QAAQ;AACV,cAAM;AACN,eAAO;AAAA,MACT;AAAA,MACA,IAAI,SAAS;AACX,cAAM;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,MAAY;AACxB,QAAI,QAAQ;AACV,YAAM,IAAI;AAAA,QACR,SAAS,QAAQ;AAAA,MAEnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAA0C;AAAA,IAC9C;AAAA,IACA,IAAI,OAAa;AACf,YAAM;AACN,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,IAAI,QAAe;AACjB,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,SAA6B;AAC/B,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,UAAqC;AACvC,YAAM;AACN,aAAO;AAAA,IACT;AAAA,IACA,IAAI,SAAyB;AAC3B,YAAM;AACN,UAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ,CAAC;AAC1C,UAAI,CAAC,QAAQ,QAAQ;AACnB,cAAM,IAAI;AAAA,UACR,SAAS,QAAQ;AAAA,QACnB;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,SAAS,QAAQ,YAAY,QAAQ,MAAM,wBACvC,QAAQ,IAAI,CAAC,UAAU,MAAM,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,MAEzD;AAAA,IACF;AAAA,IACA,OAAO,YAAY;AACjB,UAAI,OAAQ;AACZ,eAAS;AACT,YAAM,QAAQ,QAAQ;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAY,MAAM;AAChB,eAAS;AAAA,IACX;AAAA,EACF;AACF;","names":[]}