@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.
- package/README.md +118 -42
- package/bin/axe.js +313 -98
- package/dist/{loader/__fixtures__/layouts/app.load.cjs → automation/actions.cjs} +3 -13
- package/dist/automation/actions.cjs.map +1 -0
- package/dist/automation/actions.d.cts +57 -0
- package/dist/automation/actions.d.ts +57 -0
- package/dist/automation/actions.js +1 -0
- package/dist/automation/actions.js.map +1 -0
- package/dist/automation/actions_executor.cjs +101 -0
- package/dist/automation/actions_executor.cjs.map +1 -0
- package/dist/automation/actions_executor.d.cts +16 -0
- package/dist/automation/actions_executor.d.ts +16 -0
- package/dist/automation/actions_executor.js +76 -0
- package/dist/automation/actions_executor.js.map +1 -0
- package/dist/automation/connection.cjs +86 -0
- package/dist/automation/connection.cjs.map +1 -0
- package/dist/automation/connection.d.cts +18 -0
- package/dist/automation/connection.d.ts +18 -0
- package/dist/automation/connection.js +51 -0
- package/dist/automation/connection.js.map +1 -0
- package/dist/{middleware/__fixtures__/middleware/sequence.cjs → automation/errors.cjs} +25 -22
- package/dist/automation/errors.cjs.map +1 -0
- package/dist/automation/errors.d.cts +31 -0
- package/dist/automation/errors.d.ts +31 -0
- package/dist/automation/errors.js +24 -0
- package/dist/automation/errors.js.map +1 -0
- package/dist/automation/index.cjs +49 -0
- package/dist/automation/index.cjs.map +1 -0
- package/dist/automation/index.d.cts +16 -0
- package/dist/automation/index.d.ts +16 -0
- package/dist/automation/index.js +15 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/introspection_reader.cjs +75 -0
- package/dist/automation/introspection_reader.cjs.map +1 -0
- package/dist/automation/introspection_reader.d.cts +20 -0
- package/dist/automation/introspection_reader.d.ts +20 -0
- package/dist/automation/introspection_reader.js +48 -0
- package/dist/automation/introspection_reader.js.map +1 -0
- package/dist/automation/locator.cjs +102 -0
- package/dist/automation/locator.cjs.map +1 -0
- package/dist/automation/locator.d.cts +51 -0
- package/dist/automation/locator.d.ts +51 -0
- package/dist/automation/locator.js +75 -0
- package/dist/automation/locator.js.map +1 -0
- package/dist/{loader/__fixtures__/views/test/page.load.cjs → automation/observation.cjs} +3 -13
- package/dist/automation/observation.cjs.map +1 -0
- package/dist/automation/observation.d.cts +44 -0
- package/dist/automation/observation.d.ts +44 -0
- package/dist/automation/observation.js +1 -0
- package/dist/automation/observation.js.map +1 -0
- package/dist/{controller/__fixtures__/controllers/test.cjs → automation/receipts.cjs} +3 -15
- package/dist/automation/receipts.cjs.map +1 -0
- package/dist/automation/receipts.d.cts +27 -0
- package/dist/automation/receipts.d.ts +27 -0
- package/dist/automation/receipts.js +1 -0
- package/dist/automation/receipts.js.map +1 -0
- package/dist/automation/scenario.cjs +696 -0
- package/dist/automation/scenario.cjs.map +1 -0
- package/dist/automation/scenario.d.cts +89 -0
- package/dist/automation/scenario.d.ts +89 -0
- package/dist/automation/scenario.js +660 -0
- package/dist/automation/scenario.js.map +1 -0
- package/dist/automation/scrolling.cjs +17 -0
- package/dist/automation/scrolling.cjs.map +1 -0
- package/dist/automation/scrolling.d.cts +51 -0
- package/dist/automation/scrolling.d.ts +51 -0
- package/dist/automation/scrolling.js +1 -0
- package/dist/automation/scrolling.js.map +1 -0
- package/dist/automation/scrolling_executor.cjs +109 -0
- package/dist/automation/scrolling_executor.cjs.map +1 -0
- package/dist/automation/scrolling_executor.d.cts +13 -0
- package/dist/automation/scrolling_executor.d.ts +13 -0
- package/dist/automation/scrolling_executor.js +84 -0
- package/dist/automation/scrolling_executor.js.map +1 -0
- package/dist/automation/target_identity.cjs +17 -0
- package/dist/automation/target_identity.cjs.map +1 -0
- package/dist/automation/target_identity.d.cts +28 -0
- package/dist/automation/target_identity.d.ts +28 -0
- package/dist/automation/target_identity.js +1 -0
- package/dist/automation/target_identity.js.map +1 -0
- package/dist/automation/target_registry.cjs +148 -0
- package/dist/automation/target_registry.cjs.map +1 -0
- package/dist/automation/target_registry.d.cts +32 -0
- package/dist/automation/target_registry.d.ts +32 -0
- package/dist/automation/target_registry.js +122 -0
- package/dist/automation/target_registry.js.map +1 -0
- package/dist/automation/waits.cjs +17 -0
- package/dist/automation/waits.cjs.map +1 -0
- package/dist/automation/waits.d.cts +44 -0
- package/dist/automation/waits.d.ts +44 -0
- package/dist/automation/waits.js +1 -0
- package/dist/automation/waits.js.map +1 -0
- package/dist/automation/waits_executor.cjs +104 -0
- package/dist/automation/waits_executor.cjs.map +1 -0
- package/dist/automation/waits_executor.d.cts +14 -0
- package/dist/automation/waits_executor.d.ts +14 -0
- package/dist/automation/waits_executor.js +79 -0
- package/dist/automation/waits_executor.js.map +1 -0
- package/dist/bridge/backend_bridge.cjs.map +1 -1
- package/dist/bridge/backend_bridge.js.map +1 -1
- package/dist/client/index.cjs +78 -21
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +19 -3
- package/dist/client/index.d.ts +19 -3
- package/dist/client/index.js +80 -22
- package/dist/client/index.js.map +1 -1
- package/dist/client/renderer_log_transport.cjs +151 -0
- package/dist/client/renderer_log_transport.cjs.map +1 -0
- package/dist/client/renderer_log_transport.d.cts +54 -0
- package/dist/client/renderer_log_transport.d.ts +54 -0
- package/dist/client/renderer_log_transport.js +123 -0
- package/dist/client/renderer_log_transport.js.map +1 -0
- package/dist/codegen/controller_registration_generator.cjs +13 -2
- package/dist/codegen/controller_registration_generator.cjs.map +1 -1
- package/dist/codegen/controller_registration_generator.d.cts +12 -1
- package/dist/codegen/controller_registration_generator.d.ts +12 -1
- package/dist/codegen/controller_registration_generator.js +10 -1
- package/dist/codegen/controller_registration_generator.js.map +1 -1
- package/dist/codegen/index.d.cts +1 -0
- package/dist/codegen/index.d.ts +1 -0
- package/dist/codegen/preload_generator.cjs +13 -6
- package/dist/codegen/preload_generator.cjs.map +1 -1
- package/dist/codegen/preload_generator.d.cts +11 -2
- package/dist/codegen/preload_generator.d.ts +11 -2
- package/dist/codegen/preload_generator.js +13 -6
- package/dist/codegen/preload_generator.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +95 -44
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +95 -44
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/codegen/type_generator.cjs +1 -0
- package/dist/codegen/type_generator.cjs.map +1 -1
- package/dist/codegen/type_generator.js +1 -0
- package/dist/codegen/type_generator.js.map +1 -1
- package/dist/config/config_parser.cjs +95 -4
- package/dist/config/config_parser.cjs.map +1 -1
- package/dist/config/config_parser.d.cts +10 -2
- package/dist/config/config_parser.d.ts +10 -2
- package/dist/config/config_parser.js +92 -3
- package/dist/config/config_parser.js.map +1 -1
- package/dist/config/index.cjs +6 -2
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.cts +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +8 -2
- package/dist/config/index.js.map +1 -1
- package/dist/controller/controller_resolver.cjs +51 -3
- package/dist/controller/controller_resolver.cjs.map +1 -1
- package/dist/controller/controller_resolver.d.cts +27 -4
- package/dist/controller/controller_resolver.d.ts +27 -4
- package/dist/controller/controller_resolver.js +48 -2
- package/dist/controller/controller_resolver.js.map +1 -1
- package/dist/controller/index.cjs +6 -2
- package/dist/controller/index.cjs.map +1 -1
- package/dist/controller/index.d.cts +1 -1
- package/dist/controller/index.d.ts +1 -1
- package/dist/controller/index.js +4 -2
- package/dist/controller/index.js.map +1 -1
- package/dist/dev/wood_dev_server.cjs +4 -1
- package/dist/dev/wood_dev_server.cjs.map +1 -1
- package/dist/dev/wood_dev_server.js +5 -2
- package/dist/dev/wood_dev_server.js.map +1 -1
- package/dist/dev/yaml_watcher.cjs +1 -1
- package/dist/dev/yaml_watcher.cjs.map +1 -1
- package/dist/dev/yaml_watcher.d.cts +4 -0
- package/dist/dev/yaml_watcher.d.ts +4 -0
- package/dist/dev/yaml_watcher.js +1 -1
- package/dist/dev/yaml_watcher.js.map +1 -1
- package/dist/frontend/frontend_lifecycle.cjs +74 -0
- package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
- package/dist/frontend/frontend_lifecycle.d.cts +50 -0
- package/dist/frontend/frontend_lifecycle.d.ts +50 -0
- package/dist/frontend/frontend_lifecycle.js +50 -0
- package/dist/frontend/frontend_lifecycle.js.map +1 -0
- package/dist/frontend/frontend_page.cjs +122 -0
- package/dist/frontend/frontend_page.cjs.map +1 -0
- package/dist/frontend/frontend_page.d.cts +62 -0
- package/dist/frontend/frontend_page.d.ts +62 -0
- package/dist/frontend/frontend_page.js +98 -0
- package/dist/frontend/frontend_page.js.map +1 -0
- package/dist/frontend/frontend_surface.cjs +249 -0
- package/dist/frontend/frontend_surface.cjs.map +1 -0
- package/dist/frontend/frontend_surface.d.cts +64 -0
- package/dist/frontend/frontend_surface.d.ts +64 -0
- package/dist/frontend/frontend_surface.js +224 -0
- package/dist/frontend/frontend_surface.js.map +1 -0
- package/dist/frontend/index.cjs +52 -0
- package/dist/frontend/index.cjs.map +1 -0
- package/dist/frontend/index.d.cts +10 -0
- package/dist/frontend/index.d.ts +10 -0
- package/dist/frontend/index.js +19 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/page_catalog.cjs +135 -0
- package/dist/frontend/page_catalog.cjs.map +1 -0
- package/dist/frontend/page_catalog.d.cts +56 -0
- package/dist/frontend/page_catalog.d.ts +56 -0
- package/dist/frontend/page_catalog.js +108 -0
- package/dist/frontend/page_catalog.js.map +1 -0
- package/dist/frontend/tracked_transport.cjs +55 -0
- package/dist/frontend/tracked_transport.cjs.map +1 -0
- package/dist/frontend/tracked_transport.d.cts +36 -0
- package/dist/frontend/tracked_transport.d.ts +36 -0
- package/dist/frontend/tracked_transport.js +31 -0
- package/dist/frontend/tracked_transport.js.map +1 -0
- package/dist/frontend/work_registry.cjs +153 -0
- package/dist/frontend/work_registry.cjs.map +1 -0
- package/dist/frontend/work_registry.d.cts +70 -0
- package/dist/frontend/work_registry.d.ts +70 -0
- package/dist/frontend/work_registry.js +128 -0
- package/dist/frontend/work_registry.js.map +1 -0
- package/dist/index.cjs +24 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/dist/main/index.cjs +10 -0
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +14 -2
- package/dist/main/index.d.ts +14 -2
- package/dist/main/index.js +16 -0
- package/dist/main/index.js.map +1 -1
- package/dist/middleware/middleware_resolver.cjs +22 -1
- package/dist/middleware/middleware_resolver.cjs.map +1 -1
- package/dist/middleware/middleware_resolver.d.cts +13 -1
- package/dist/middleware/middleware_resolver.d.ts +13 -1
- package/dist/middleware/middleware_resolver.js +22 -1
- package/dist/middleware/middleware_resolver.js.map +1 -1
- package/dist/navigation/automation_introspection.cjs +110 -0
- package/dist/navigation/automation_introspection.cjs.map +1 -0
- package/dist/navigation/automation_introspection.d.cts +60 -0
- package/dist/navigation/automation_introspection.d.ts +60 -0
- package/dist/navigation/automation_introspection.js +85 -0
- package/dist/navigation/automation_introspection.js.map +1 -0
- package/dist/navigation/index.cjs +10 -2
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +27 -1
- package/dist/navigation/index.d.ts +27 -1
- package/dist/navigation/index.js +6 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
- package/dist/navigation/layout_preservation.cjs.map +1 -0
- package/dist/navigation/layout_preservation.d.cts +2 -0
- package/dist/navigation/layout_preservation.d.ts +2 -0
- package/dist/navigation/layout_preservation.js +18 -0
- package/dist/navigation/layout_preservation.js.map +1 -0
- package/dist/parser/index.cjs +2 -0
- package/dist/parser/index.cjs.map +1 -1
- package/dist/parser/index.d.cts +1 -1
- package/dist/parser/index.d.ts +1 -1
- package/dist/parser/index.js +2 -1
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/operations_parser.cjs +6 -0
- package/dist/parser/operations_parser.cjs.map +1 -1
- package/dist/parser/operations_parser.d.cts +9 -2
- package/dist/parser/operations_parser.d.ts +9 -2
- package/dist/parser/operations_parser.js +5 -0
- package/dist/parser/operations_parser.js.map +1 -1
- package/dist/parser/views_parser.cjs.map +1 -1
- package/dist/parser/views_parser.js.map +1 -1
- package/dist/router/index.d.cts +1 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/router/wood_router.cjs +35 -3
- package/dist/router/wood_router.cjs.map +1 -1
- package/dist/router/wood_router.d.cts +15 -0
- package/dist/router/wood_router.d.ts +15 -0
- package/dist/router/wood_router.js +36 -4
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/get_container.cjs +9 -34
- package/dist/runtime/get_container.cjs.map +1 -1
- package/dist/runtime/get_container.d.cts +24 -4
- package/dist/runtime/get_container.d.ts +24 -4
- package/dist/runtime/get_container.js +8 -23
- package/dist/runtime/get_container.js.map +1 -1
- package/dist/runtime/index.cjs +9 -0
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +5 -2
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +10 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderer_config_extension.cjs +50 -0
- package/dist/runtime/renderer_config_extension.cjs.map +1 -0
- package/dist/runtime/renderer_config_extension.d.cts +19 -0
- package/dist/runtime/renderer_config_extension.d.ts +19 -0
- package/dist/runtime/renderer_config_extension.js +24 -0
- package/dist/runtime/renderer_config_extension.js.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.js +48 -0
- package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
- package/dist/runtime/runtime.cjs +14 -0
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +2 -1
- package/dist/runtime/runtime.d.ts +2 -1
- package/dist/runtime/runtime.js +14 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/stick/index.cjs.map +1 -1
- package/dist/stick/index.js.map +1 -1
- package/dist/testing/automation_assertions.cjs +417 -0
- package/dist/testing/automation_assertions.cjs.map +1 -0
- package/dist/testing/automation_assertions.d.cts +44 -0
- package/dist/testing/automation_assertions.d.ts +44 -0
- package/dist/testing/automation_assertions.js +385 -0
- package/dist/testing/automation_assertions.js.map +1 -0
- package/dist/testing/browser.cjs +130 -57
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +10 -4
- package/dist/testing/browser.d.ts +10 -4
- package/dist/testing/browser.js +132 -53
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.cjs +28 -8
- package/dist/testing/create_controller_harness.cjs.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +18 -2
- package/dist/testing/create_controller_harness.d.ts +18 -2
- package/dist/testing/create_controller_harness.js +28 -8
- package/dist/testing/create_controller_harness.js.map +1 -1
- package/dist/testing/create_router_bridge.d.cts +1 -0
- package/dist/testing/create_router_bridge.d.ts +1 -0
- package/dist/testing/create_test_router.d.cts +1 -0
- package/dist/testing/create_test_router.d.ts +1 -0
- package/dist/testing/geometry.cjs +109 -0
- package/dist/testing/geometry.cjs.map +1 -0
- package/dist/testing/geometry.d.cts +45 -0
- package/dist/testing/geometry.d.ts +45 -0
- package/dist/testing/geometry.js +79 -0
- package/dist/testing/geometry.js.map +1 -0
- package/dist/testing/index.cjs +62 -2
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +23 -4
- package/dist/testing/index.d.ts +23 -4
- package/dist/testing/index.js +50 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
- package/dist/testing/test_wood.cjs.map +1 -0
- package/dist/testing/test_wood.d.cts +16 -0
- package/dist/testing/test_wood.d.ts +16 -0
- package/dist/testing/test_wood.js +12 -0
- package/dist/testing/test_wood.js.map +1 -0
- package/dist/testing/test_wood_config.cjs +272 -0
- package/dist/testing/test_wood_config.cjs.map +1 -0
- package/dist/testing/test_wood_config.d.cts +111 -0
- package/dist/testing/test_wood_config.d.ts +111 -0
- package/dist/testing/test_wood_config.js +247 -0
- package/dist/testing/test_wood_config.js.map +1 -0
- package/dist/testing/wood_config_source.cjs +146 -0
- package/dist/testing/wood_config_source.cjs.map +1 -0
- package/dist/testing/wood_config_source.d.cts +36 -0
- package/dist/testing/wood_config_source.d.ts +36 -0
- package/dist/testing/wood_config_source.js +112 -0
- package/dist/testing/wood_config_source.js.map +1 -0
- package/dist/testing/wood_env_renderer.cjs +210 -0
- package/dist/testing/wood_env_renderer.cjs.map +1 -0
- package/dist/testing/wood_env_renderer.d.cts +74 -0
- package/dist/testing/wood_env_renderer.d.ts +74 -0
- package/dist/testing/wood_env_renderer.js +188 -0
- package/dist/testing/wood_env_renderer.js.map +1 -0
- package/dist/testing/wood_test_selection.cjs +94 -0
- package/dist/testing/wood_test_selection.cjs.map +1 -0
- package/dist/testing/wood_test_selection.d.cts +39 -0
- package/dist/testing/wood_test_selection.d.ts +39 -0
- package/dist/testing/wood_test_selection.js +68 -0
- package/dist/testing/wood_test_selection.js.map +1 -0
- package/dist/trace-testing/index.d.cts +1 -2
- package/dist/trace-testing/index.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.cjs +1 -1
- package/dist/trace-testing/trace_recorder.cjs.map +1 -1
- package/dist/trace-testing/trace_recorder.d.cts +1 -2
- package/dist/trace-testing/trace_recorder.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.js +1 -1
- package/dist/trace-testing/trace_recorder.js.map +1 -1
- package/dist/trace-transport/index.d.cts +1 -1
- package/dist/trace-transport/index.d.ts +1 -1
- package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
- package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
- package/dist/tracing/index.cjs +9 -2
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +3 -2
- package/dist/tracing/index.d.ts +3 -2
- package/dist/tracing/index.js +7 -1
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
- package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
- package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
- package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.js +48 -6
- package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
- package/dist/tracing/trace_batch_adapter.cjs +110 -0
- package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
- package/dist/tracing/trace_batch_adapter.d.cts +36 -0
- package/dist/tracing/trace_batch_adapter.d.ts +36 -0
- package/dist/tracing/trace_batch_adapter.js +86 -0
- package/dist/tracing/trace_batch_adapter.js.map +1 -0
- package/dist/tracing/trace_commit_writer.d.cts +1 -1
- package/dist/tracing/trace_commit_writer.d.ts +1 -1
- package/dist/tracing/trace_hub.cjs +87 -20
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +1 -1
- package/dist/tracing/trace_hub.d.ts +1 -1
- package/dist/tracing/trace_hub.js +85 -20
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +21 -6
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +13 -4
- package/dist/tracing/trace_provider.d.ts +13 -4
- package/dist/tracing/trace_provider.js +22 -7
- package/dist/tracing/trace_provider.js.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
- package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
- package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
- package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
- package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.js +2 -0
- package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
- package/dist/transport/build_transport_bridge.cjs +4 -2
- package/dist/transport/build_transport_bridge.cjs.map +1 -1
- package/dist/transport/build_transport_bridge.d.cts +7 -1
- package/dist/transport/build_transport_bridge.d.ts +7 -1
- package/dist/transport/build_transport_bridge.js +2 -1
- package/dist/transport/build_transport_bridge.js.map +1 -1
- package/dist/transport/in_process_router_transport.d.cts +1 -0
- package/dist/transport/in_process_router_transport.d.ts +1 -0
- package/dist/transport/index.d.cts +1 -0
- package/dist/transport/index.d.ts +1 -0
- package/dist/types/config.cjs.map +1 -1
- package/dist/types/config.d.cts +47 -1
- package/dist/types/config.d.ts +47 -1
- package/dist/types/context.cjs +12 -0
- package/dist/types/context.cjs.map +1 -1
- package/dist/types/context.d.cts +27 -1
- package/dist/types/context.d.ts +27 -1
- package/dist/types/context.js +4 -0
- package/dist/types/context.js.map +1 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/operations.cjs.map +1 -1
- package/dist/types/operations.d.cts +2 -0
- package/dist/types/operations.d.ts +2 -0
- package/docs/axe.md +706 -0
- package/package.json +19 -5
- package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
- package/src/components/NavigationShell.svelte +126 -49
- package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.js +0 -12
- package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
- package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
- package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
- package/dist/controller/__fixtures__/controllers/test.js +0 -9
- package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
- package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
- package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
- package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
- package/dist/middleware/__fixtures__/middleware/sequence.js.map +0 -1
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/index.ts"],"sourcesContent":["export {
|
|
1
|
+
{"version":3,"sources":["../../src/config/index.ts"],"sourcesContent":["export {\n parseConfig,\n resolveRendererTraceBatching,\n RENDERER_TRACE_BATCHING_DEFAULTS,\n} from './config_parser.js';\nexport type {\n ObservabilityConfig,\n RendererTraceBatchingConfig,\n} from '../types/config.js';\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
|
|
@@ -29,7 +29,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var controller_resolver_exports = {};
|
|
30
30
|
__export(controller_resolver_exports, {
|
|
31
31
|
ControllerResolver: () => ControllerResolver,
|
|
32
|
-
buildControllerArgs: () => buildControllerArgs
|
|
32
|
+
buildControllerArgs: () => buildControllerArgs,
|
|
33
|
+
buildOperationContext: () => buildOperationContext,
|
|
34
|
+
usesOperationContext: () => usesOperationContext
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(controller_resolver_exports);
|
|
35
37
|
var import_path = __toESM(require("path"), 1);
|
|
@@ -43,6 +45,8 @@ class ControllerResolver {
|
|
|
43
45
|
constructor(controllersDir, options) {
|
|
44
46
|
this.classCache = /* @__PURE__ */ new Map();
|
|
45
47
|
this.pathCache = /* @__PURE__ */ new Map();
|
|
48
|
+
// name -> import path
|
|
49
|
+
this.loaderCache = /* @__PURE__ */ new Map();
|
|
46
50
|
this.baseDir = controllersDir;
|
|
47
51
|
this.mode = options?.mode ?? (process.env.WOOD_MODE === "development" ? "dev" : "bundled");
|
|
48
52
|
}
|
|
@@ -50,7 +54,20 @@ class ControllerResolver {
|
|
|
50
54
|
* Check whether a controller name has been pre-registered (class or path).
|
|
51
55
|
*/
|
|
52
56
|
has(name) {
|
|
53
|
-
return this.classCache.has(name) || this.pathCache.has(name);
|
|
57
|
+
return this.classCache.has(name) || this.pathCache.has(name) || this.loaderCache.has(name);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register a lazy module loader for a controller. The loader is the
|
|
61
|
+
* CALLER's `() => import('...literal specifier...')`, so the import runs in
|
|
62
|
+
* the caller's module resolution (bundler/test-runner identity) instead of
|
|
63
|
+
* a raw filesystem import — same class identity as every other import of
|
|
64
|
+
* that module. Invoked only on first resolution.
|
|
65
|
+
*/
|
|
66
|
+
registerLoader(name, loader) {
|
|
67
|
+
if (typeof loader !== "function") {
|
|
68
|
+
throw new Error(`registerLoader("${name}"): expected a () => Promise<module> function`);
|
|
69
|
+
}
|
|
70
|
+
this.loaderCache.set(name, loader);
|
|
54
71
|
}
|
|
55
72
|
/**
|
|
56
73
|
* Register an import path for a controller. The controller will be lazily
|
|
@@ -75,6 +92,19 @@ class ControllerResolver {
|
|
|
75
92
|
async resolveClass(controllerName) {
|
|
76
93
|
const cached = this.classCache.get(controllerName);
|
|
77
94
|
if (cached) return cached;
|
|
95
|
+
const loader = this.loaderCache.get(controllerName);
|
|
96
|
+
if (loader) {
|
|
97
|
+
const mod = await loader();
|
|
98
|
+
const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];
|
|
99
|
+
if (!ControllerClass || typeof ControllerClass !== "function") {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Controller "${controllerName}": registered loader's module does not export a class`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
this.classCache.set(controllerName, ControllerClass);
|
|
105
|
+
logger.debug(`Resolved controller "${controllerName}" from registered loader`);
|
|
106
|
+
return ControllerClass;
|
|
107
|
+
}
|
|
78
108
|
const importPath = this.pathCache.get(controllerName);
|
|
79
109
|
if (importPath) {
|
|
80
110
|
const mod = await import(toImportSpecifier(importPath));
|
|
@@ -154,6 +184,22 @@ Registered controllers: [${Array.from(this.pathCache.keys()).join(", ")}]`
|
|
|
154
184
|
this.classCache.clear();
|
|
155
185
|
}
|
|
156
186
|
}
|
|
187
|
+
function usesOperationContext(ControllerClass) {
|
|
188
|
+
return ControllerClass?.woodContext === "operation";
|
|
189
|
+
}
|
|
190
|
+
function buildOperationContext(operation, ipcContext) {
|
|
191
|
+
const state = ipcContext.context ?? {};
|
|
192
|
+
return {
|
|
193
|
+
operation,
|
|
194
|
+
input: ipcContext.body,
|
|
195
|
+
state,
|
|
196
|
+
sender: ipcContext.sender,
|
|
197
|
+
windowId: ipcContext.windowId,
|
|
198
|
+
get(key) {
|
|
199
|
+
return state[key];
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
157
203
|
function buildControllerArgs(ipcContext, container) {
|
|
158
204
|
return {
|
|
159
205
|
req: {
|
|
@@ -179,6 +225,8 @@ function buildControllerArgs(ipcContext, container) {
|
|
|
179
225
|
// Annotate the CommonJS export names for ESM import in node:
|
|
180
226
|
0 && (module.exports = {
|
|
181
227
|
ControllerResolver,
|
|
182
|
-
buildControllerArgs
|
|
228
|
+
buildControllerArgs,
|
|
229
|
+
buildOperationContext,
|
|
230
|
+
usesOperationContext
|
|
183
231
|
});
|
|
184
232
|
//# sourceMappingURL=controller_resolver.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/controller/controller_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport { getLogger } from '@noego/logger';\nimport type { IpcContext, ControllerArgs } from '../types/context.cjs';\n\nconst logger = getLogger('wood:controller');\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 ControllerResolver {\n private baseDir: string;\n private classCache = new Map<string, any>();\n private pathCache = new Map<string, string>(); // name -> import path\n private mode: 'bundled' | 'dev';\n\n constructor(controllersDir: string, options?: { mode?: 'bundled' | 'dev' }) {\n this.baseDir = controllersDir;\n // Default to bundled mode for safety. Dev mode must be explicitly opted into.\n this.mode = options?.mode ?? (process.env.WOOD_MODE === 'development' ? 'dev' : 'bundled');\n }\n\n /**\n * Check whether a controller name has been pre-registered (class or path).\n */\n has(name: string): boolean {\n return this.classCache.has(name) || this.pathCache.has(name);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed. This avoids circular dependencies\n * at module load time.\n */\n registerPath(name: string, importPath: string): void {\n if (!importPath) {\n throw new Error(`registerPath(\"${name}\"): importPath cannot be empty`);\n }\n this.pathCache.set(name, importPath);\n }\n\n /**\n * Resolve a controller name to its class.\n *\n * 1. Check class cache (already imported)\n * 2. Check path cache (registered via registerPath) and lazily import\n * 3. In dev mode only: fall back to filesystem resolution\n *\n * Classes are cached -- same class reference returned for same name.\n */\n async resolveClass(controllerName: string): Promise<any> {\n const cached = this.classCache.get(controllerName);\n if (cached) return cached;\n\n // Check if import path is registered — lazily load it\n const importPath = this.pathCache.get(controllerName);\n if (importPath) {\n const mod = await import(toImportSpecifier(importPath));\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\" at ${importPath}: module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered path`);\n return ControllerClass;\n }\n\n if (this.mode === 'bundled') {\n throw new Error(\n `Controller \"${controllerName}\" is not registered. ` +\n `In bundled mode, all controllers must be pre-registered via controllers.generated.ts. ` +\n `Run \"npx wood build\" to regenerate the registration file.\\n` +\n `Registered controllers: [${Array.from(this.pathCache.keys()).join(', ')}]`\n );\n }\n\n // Dev mode: attempt dynamic filesystem imports\n return this.resolveFromFilesystem(controllerName);\n }\n\n private async resolveFromFilesystem(controllerName: string): Promise<any> {\n const basePath = path.resolve(this.baseDir, controllerName);\n const candidates = [\n basePath + '.ts',\n basePath + '.controller.ts',\n basePath + '.js',\n basePath + '.controller.js',\n path.resolve(this.baseDir, controllerName, 'index.ts'),\n path.resolve(this.baseDir, controllerName, 'index.js'),\n ];\n\n let mod: any;\n let loaded = false;\n\n for (const candidate of candidates) {\n try {\n mod = await import(toImportSpecifier(candidate));\n loaded = true;\n break;\n } catch {\n // Try next candidate\n }\n }\n\n if (!loaded) {\n throw new Error(\n `Controller \"${controllerName}\" not found. Searched:\\n` +\n candidates.map(c => ` - ${c}`).join('\\n')\n );\n }\n\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": module does not export a class`\n );\n }\n\n logger.debug(`Resolved controller \"${controllerName}\" from ${this.baseDir}`);\n this.classCache.set(controllerName, ControllerClass);\n return ControllerClass;\n }\n\n /**\n * Create a controller instance using IoC container.\n * Per-request scoped: container.extend() creates an isolated scope.\n */\n async createInstance(ControllerClass: any, container: any): Promise<any> {\n const scopedContainer = container.extend();\n return scopedContainer.instance(ControllerClass);\n }\n\n /**\n * Pre-register a controller class by name so that resolveClass()\n * finds it in the cache without attempting a filesystem import.\n */\n register(name: string, ControllerClass: any): void {\n if (typeof ControllerClass !== 'function') {\n throw new Error(`register(\"${name}\"): expected a class/constructor, got ${typeof ControllerClass}`);\n }\n this.classCache.set(name, ControllerClass);\n }\n\n clearCache(): void {\n this.classCache.clear();\n }\n}\n\n/**\n * Build controller args from IPC context.\n * Creates a fake req/res that matches the Dinner web pattern so\n * existing controllers work without modification.\n */\nexport function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs {\n return {\n req: {\n body: ipcContext.body ?? {},\n params: ipcContext.params ?? {},\n query: ipcContext.query ?? {},\n context: ipcContext.context ?? {},\n headers: {},\n },\n res: {\n status: (_code: number) => {},\n cookie: (_name: string, _value: string, _opts?: unknown) => {},\n clearCookie: (_name: string, _opts?: unknown) => {},\n set: (_header: string, _value: string) => {},\n },\n container,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,sBAA8B;AAC9B,oBAA0B;AAG1B,MAAM,aAAS,yBAAU,iBAAiB;AAI1C,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,YAAAA,QAAK,WAAW,IAAI,QAAI,+BAAc,IAAI,EAAE,OAAO;AAC5D;AAEO,MAAM,mBAAmB;AAAA,EAM9B,YAAY,gBAAwB,SAAwC;AAJ5E,SAAQ,aAAa,oBAAI,IAAiB;AAC1C,SAAQ,YAAY,oBAAI,IAAoB;AAI1C,SAAK,UAAU;AAEf,SAAK,OAAO,SAAS,SAAS,QAAQ,IAAI,cAAc,gBAAgB,QAAQ;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAuB;AACzB,WAAO,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,UAAU,IAAI,IAAI;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,MAAc,YAA0B;AACnD,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,iBAAiB,IAAI,gCAAgC;AAAA,IACvE;AACA,SAAK,UAAU,IAAI,MAAM,UAAU;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,aAAa,gBAAsC;AACvD,UAAM,SAAS,KAAK,WAAW,IAAI,cAAc;AACjD,QAAI,OAAQ,QAAO;AAGnB,UAAM,aAAa,KAAK,UAAU,IAAI,cAAc;AACpD,QAAI,YAAY;AACd,YAAM,MAAM,MAAM,OAAO,kBAAkB,UAAU;AACrD,YAAM,kBAAkB,IAAI,WAAW,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC,CAAC;AAC9D,UAAI,CAAC,mBAAmB,OAAO,oBAAoB,YAAY;AAC7D,cAAM,IAAI;AAAA,UACR,eAAe,cAAc,QAAQ,UAAU;AAAA,QACjD;AAAA,MACF;AACA,WAAK,WAAW,IAAI,gBAAgB,eAAe;AACnD,aAAO,MAAM,wBAAwB,cAAc,wBAAwB;AAC3E,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,IAAI;AAAA,QACR,eAAe,cAAc;AAAA,2BAGD,MAAM,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,MAC1E;AAAA,IACF;AAGA,WAAO,KAAK,sBAAsB,cAAc;AAAA,EAClD;AAAA,EAEA,MAAc,sBAAsB,gBAAsC;AACxE,UAAM,WAAW,YAAAA,QAAK,QAAQ,KAAK,SAAS,cAAc;AAC1D,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAAA,QAAK,QAAQ,KAAK,SAAS,gBAAgB,UAAU;AAAA,MACrD,YAAAA,QAAK,QAAQ,KAAK,SAAS,gBAAgB,UAAU;AAAA,IACvD;AAEA,QAAI;AACJ,QAAI,SAAS;AAEb,eAAW,aAAa,YAAY;AAClC,UAAI;AACF,cAAM,MAAM,OAAO,kBAAkB,SAAS;AAC9C,iBAAS;AACT;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,eAAe,cAAc;AAAA,IAC7B,WAAW,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,MAC3C;AAAA,IACF;AAEA,UAAM,kBAAkB,IAAI,WAAW,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC,CAAC;AAC9D,QAAI,CAAC,mBAAmB,OAAO,oBAAoB,YAAY;AAC7D,YAAM,IAAI;AAAA,QACR,eAAe,cAAc;AAAA,MAC/B;AAAA,IACF;AAEA,WAAO,MAAM,wBAAwB,cAAc,UAAU,KAAK,OAAO,EAAE;AAC3E,SAAK,WAAW,IAAI,gBAAgB,eAAe;AACnD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,iBAAsB,WAA8B;AACvE,UAAM,kBAAkB,UAAU,OAAO;AACzC,WAAO,gBAAgB,SAAS,eAAe;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,MAAc,iBAA4B;AACjD,QAAI,OAAO,oBAAoB,YAAY;AACzC,YAAM,IAAI,MAAM,aAAa,IAAI,yCAAyC,OAAO,eAAe,EAAE;AAAA,IACpG;AACA,SAAK,WAAW,IAAI,MAAM,eAAe;AAAA,EAC3C;AAAA,EAEA,aAAmB;AACjB,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;AAOO,SAAS,oBAAoB,YAAwB,WAAoC;AAC9F,SAAO;AAAA,IACL,KAAK;AAAA,MACH,MAAM,WAAW,QAAQ,CAAC;AAAA,MAC1B,QAAQ,WAAW,UAAU,CAAC;AAAA,MAC9B,OAAO,WAAW,SAAS,CAAC;AAAA,MAC5B,SAAS,WAAW,WAAW,CAAC;AAAA,MAChC,SAAS,CAAC;AAAA,IACZ;AAAA,IACA,KAAK;AAAA,MACH,QAAQ,CAAC,UAAkB;AAAA,MAAC;AAAA,MAC5B,QAAQ,CAAC,OAAe,QAAgB,UAAoB;AAAA,MAAC;AAAA,MAC7D,aAAa,CAAC,OAAe,UAAoB;AAAA,MAAC;AAAA,MAClD,KAAK,CAAC,SAAiB,WAAmB;AAAA,MAAC;AAAA,IAC7C;AAAA,IACA;AAAA,EACF;AACF;","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/controller/controller_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport { getLogger } from '@noego/logger';\nimport type { IpcContext, ControllerArgs } from '../types/context.cjs';\n\nconst logger = getLogger('wood:controller');\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 ControllerResolver {\n private baseDir: string;\n private classCache = new Map<string, any>();\n private pathCache = new Map<string, string>(); // name -> import path\n private loaderCache = new Map<string, () => Promise<unknown>>(); // name -> lazy module loader\n private mode: 'bundled' | 'dev';\n\n constructor(controllersDir: string, options?: { mode?: 'bundled' | 'dev' }) {\n this.baseDir = controllersDir;\n // Default to bundled mode for safety. Dev mode must be explicitly opted into.\n this.mode = options?.mode ?? (process.env.WOOD_MODE === 'development' ? 'dev' : 'bundled');\n }\n\n /**\n * Check whether a controller name has been pre-registered (class or path).\n */\n has(name: string): boolean {\n return this.classCache.has(name) || this.pathCache.has(name) || this.loaderCache.has(name);\n }\n\n /**\n * Register a lazy module loader for a controller. The loader is the\n * CALLER's `() => import('...literal specifier...')`, so the import runs in\n * the caller's module resolution (bundler/test-runner identity) instead of\n * a raw filesystem import — same class identity as every other import of\n * that module. Invoked only on first resolution.\n */\n registerLoader(name: string, loader: () => Promise<unknown>): void {\n if (typeof loader !== 'function') {\n throw new Error(`registerLoader(\"${name}\"): expected a () => Promise<module> function`);\n }\n this.loaderCache.set(name, loader);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed. This avoids circular dependencies\n * at module load time.\n */\n registerPath(name: string, importPath: string): void {\n if (!importPath) {\n throw new Error(`registerPath(\"${name}\"): importPath cannot be empty`);\n }\n this.pathCache.set(name, importPath);\n }\n\n /**\n * Resolve a controller name to its class.\n *\n * 1. Check class cache (already imported)\n * 2. Check path cache (registered via registerPath) and lazily import\n * 3. In dev mode only: fall back to filesystem resolution\n *\n * Classes are cached -- same class reference returned for same name.\n */\n async resolveClass(controllerName: string): Promise<any> {\n const cached = this.classCache.get(controllerName);\n if (cached) return cached;\n\n // Lazy loader (caller-owned import) takes precedence: it preserves the\n // caller's module identity for the controller and its dependency graph.\n const loader = this.loaderCache.get(controllerName);\n if (loader) {\n const mod = (await loader()) as Record<string, unknown>;\n const ControllerClass = (mod.default ?? mod[Object.keys(mod)[0]]) as unknown;\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": registered loader's module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered loader`);\n return ControllerClass;\n }\n\n // Check if import path is registered — lazily load it\n const importPath = this.pathCache.get(controllerName);\n if (importPath) {\n const mod = await import(toImportSpecifier(importPath));\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\" at ${importPath}: module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered path`);\n return ControllerClass;\n }\n\n if (this.mode === 'bundled') {\n throw new Error(\n `Controller \"${controllerName}\" is not registered. ` +\n `In bundled mode, all controllers must be pre-registered via controllers.generated.ts. ` +\n `Run \"npx wood build\" to regenerate the registration file.\\n` +\n `Registered controllers: [${Array.from(this.pathCache.keys()).join(', ')}]`\n );\n }\n\n // Dev mode: attempt dynamic filesystem imports\n return this.resolveFromFilesystem(controllerName);\n }\n\n private async resolveFromFilesystem(controllerName: string): Promise<any> {\n const basePath = path.resolve(this.baseDir, controllerName);\n const candidates = [\n basePath + '.ts',\n basePath + '.controller.ts',\n basePath + '.js',\n basePath + '.controller.js',\n path.resolve(this.baseDir, controllerName, 'index.ts'),\n path.resolve(this.baseDir, controllerName, 'index.js'),\n ];\n\n let mod: any;\n let loaded = false;\n\n for (const candidate of candidates) {\n try {\n mod = await import(toImportSpecifier(candidate));\n loaded = true;\n break;\n } catch {\n // Try next candidate\n }\n }\n\n if (!loaded) {\n throw new Error(\n `Controller \"${controllerName}\" not found. Searched:\\n` +\n candidates.map(c => ` - ${c}`).join('\\n')\n );\n }\n\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": module does not export a class`\n );\n }\n\n logger.debug(`Resolved controller \"${controllerName}\" from ${this.baseDir}`);\n this.classCache.set(controllerName, ControllerClass);\n return ControllerClass;\n }\n\n /**\n * Create a controller instance using IoC container.\n * Per-request scoped: container.extend() creates an isolated scope.\n */\n async createInstance(ControllerClass: any, container: any): Promise<any> {\n const scopedContainer = container.extend();\n return scopedContainer.instance(ControllerClass);\n }\n\n /**\n * Pre-register a controller class by name so that resolveClass()\n * finds it in the cache without attempting a filesystem import.\n */\n register(name: string, ControllerClass: any): void {\n if (typeof ControllerClass !== 'function') {\n throw new Error(`register(\"${name}\"): expected a class/constructor, got ${typeof ControllerClass}`);\n }\n this.classCache.set(name, ControllerClass);\n }\n\n clearCache(): void {\n this.classCache.clear();\n }\n}\n\n/**\n * Whether a controller class opted into the native Desktop boundary\n * (`static woodContext = 'operation'`). Native actions receive a\n * WoodOperationContext; everything else keeps the legacy args pair.\n */\nexport function usesOperationContext(ControllerClass: unknown): boolean {\n return (ControllerClass as { woodContext?: string })?.woodContext === 'operation';\n}\n\n/**\n * Build the native Wood operation context for a controller action.\n * Desktop-shaped: operation identity, validated input, middleware state,\n * sender/window — no fabricated HTTP surface, no container.\n */\nexport function buildOperationContext(\n operation: string,\n ipcContext: IpcContext\n): import('../types/context.cjs').WoodOperationContext {\n const state = ipcContext.context ?? {};\n return {\n operation,\n input: ipcContext.body,\n state,\n sender: ipcContext.sender,\n windowId: ipcContext.windowId,\n get<T>(key: string): T | undefined {\n return state[key] as T | undefined;\n },\n };\n}\n\n/**\n * Build controller args from IPC context.\n * LEGACY-COMPAT: creates a fake req/res matching the Dinner web pattern so\n * pre-native controllers work without modification. New controllers declare\n * `static woodContext = 'operation'` and receive a WoodOperationContext\n * (see buildOperationContext) instead.\n */\nexport function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs {\n return {\n req: {\n body: ipcContext.body ?? {},\n params: ipcContext.params ?? {},\n query: ipcContext.query ?? {},\n context: ipcContext.context ?? {},\n headers: {},\n },\n res: {\n status: (_code: number) => {},\n cookie: (_name: string, _value: string, _opts?: unknown) => {},\n clearCookie: (_name: string, _opts?: unknown) => {},\n set: (_header: string, _value: string) => {},\n },\n container,\n };\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { IpcContext, ControllerArgs } from '../types/context.cjs';
|
|
1
|
+
import { IpcContext, ControllerArgs, WoodOperationContext } from '../types/context.cjs';
|
|
2
2
|
|
|
3
3
|
declare class ControllerResolver {
|
|
4
4
|
private baseDir;
|
|
5
5
|
private classCache;
|
|
6
6
|
private pathCache;
|
|
7
|
+
private loaderCache;
|
|
7
8
|
private mode;
|
|
8
9
|
constructor(controllersDir: string, options?: {
|
|
9
10
|
mode?: 'bundled' | 'dev';
|
|
@@ -12,6 +13,14 @@ declare class ControllerResolver {
|
|
|
12
13
|
* Check whether a controller name has been pre-registered (class or path).
|
|
13
14
|
*/
|
|
14
15
|
has(name: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Register a lazy module loader for a controller. The loader is the
|
|
18
|
+
* CALLER's `() => import('...literal specifier...')`, so the import runs in
|
|
19
|
+
* the caller's module resolution (bundler/test-runner identity) instead of
|
|
20
|
+
* a raw filesystem import — same class identity as every other import of
|
|
21
|
+
* that module. Invoked only on first resolution.
|
|
22
|
+
*/
|
|
23
|
+
registerLoader(name: string, loader: () => Promise<unknown>): void;
|
|
15
24
|
/**
|
|
16
25
|
* Register an import path for a controller. The controller will be lazily
|
|
17
26
|
* imported from this path when first needed. This avoids circular dependencies
|
|
@@ -41,11 +50,25 @@ declare class ControllerResolver {
|
|
|
41
50
|
register(name: string, ControllerClass: any): void;
|
|
42
51
|
clearCache(): void;
|
|
43
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether a controller class opted into the native Desktop boundary
|
|
55
|
+
* (`static woodContext = 'operation'`). Native actions receive a
|
|
56
|
+
* WoodOperationContext; everything else keeps the legacy args pair.
|
|
57
|
+
*/
|
|
58
|
+
declare function usesOperationContext(ControllerClass: unknown): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Build the native Wood operation context for a controller action.
|
|
61
|
+
* Desktop-shaped: operation identity, validated input, middleware state,
|
|
62
|
+
* sender/window — no fabricated HTTP surface, no container.
|
|
63
|
+
*/
|
|
64
|
+
declare function buildOperationContext(operation: string, ipcContext: IpcContext): WoodOperationContext;
|
|
44
65
|
/**
|
|
45
66
|
* Build controller args from IPC context.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
67
|
+
* LEGACY-COMPAT: creates a fake req/res matching the Dinner web pattern so
|
|
68
|
+
* pre-native controllers work without modification. New controllers declare
|
|
69
|
+
* `static woodContext = 'operation'` and receive a WoodOperationContext
|
|
70
|
+
* (see buildOperationContext) instead.
|
|
48
71
|
*/
|
|
49
72
|
declare function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs;
|
|
50
73
|
|
|
51
|
-
export { ControllerResolver, buildControllerArgs };
|
|
74
|
+
export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { IpcContext, ControllerArgs } from '../types/context.js';
|
|
1
|
+
import { IpcContext, ControllerArgs, WoodOperationContext } from '../types/context.js';
|
|
2
2
|
|
|
3
3
|
declare class ControllerResolver {
|
|
4
4
|
private baseDir;
|
|
5
5
|
private classCache;
|
|
6
6
|
private pathCache;
|
|
7
|
+
private loaderCache;
|
|
7
8
|
private mode;
|
|
8
9
|
constructor(controllersDir: string, options?: {
|
|
9
10
|
mode?: 'bundled' | 'dev';
|
|
@@ -12,6 +13,14 @@ declare class ControllerResolver {
|
|
|
12
13
|
* Check whether a controller name has been pre-registered (class or path).
|
|
13
14
|
*/
|
|
14
15
|
has(name: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Register a lazy module loader for a controller. The loader is the
|
|
18
|
+
* CALLER's `() => import('...literal specifier...')`, so the import runs in
|
|
19
|
+
* the caller's module resolution (bundler/test-runner identity) instead of
|
|
20
|
+
* a raw filesystem import — same class identity as every other import of
|
|
21
|
+
* that module. Invoked only on first resolution.
|
|
22
|
+
*/
|
|
23
|
+
registerLoader(name: string, loader: () => Promise<unknown>): void;
|
|
15
24
|
/**
|
|
16
25
|
* Register an import path for a controller. The controller will be lazily
|
|
17
26
|
* imported from this path when first needed. This avoids circular dependencies
|
|
@@ -41,11 +50,25 @@ declare class ControllerResolver {
|
|
|
41
50
|
register(name: string, ControllerClass: any): void;
|
|
42
51
|
clearCache(): void;
|
|
43
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether a controller class opted into the native Desktop boundary
|
|
55
|
+
* (`static woodContext = 'operation'`). Native actions receive a
|
|
56
|
+
* WoodOperationContext; everything else keeps the legacy args pair.
|
|
57
|
+
*/
|
|
58
|
+
declare function usesOperationContext(ControllerClass: unknown): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Build the native Wood operation context for a controller action.
|
|
61
|
+
* Desktop-shaped: operation identity, validated input, middleware state,
|
|
62
|
+
* sender/window — no fabricated HTTP surface, no container.
|
|
63
|
+
*/
|
|
64
|
+
declare function buildOperationContext(operation: string, ipcContext: IpcContext): WoodOperationContext;
|
|
44
65
|
/**
|
|
45
66
|
* Build controller args from IPC context.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
67
|
+
* LEGACY-COMPAT: creates a fake req/res matching the Dinner web pattern so
|
|
68
|
+
* pre-native controllers work without modification. New controllers declare
|
|
69
|
+
* `static woodContext = 'operation'` and receive a WoodOperationContext
|
|
70
|
+
* (see buildOperationContext) instead.
|
|
48
71
|
*/
|
|
49
72
|
declare function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs;
|
|
50
73
|
|
|
51
|
-
export { ControllerResolver, buildControllerArgs };
|
|
74
|
+
export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext };
|
|
@@ -9,6 +9,8 @@ class ControllerResolver {
|
|
|
9
9
|
constructor(controllersDir, options) {
|
|
10
10
|
this.classCache = /* @__PURE__ */ new Map();
|
|
11
11
|
this.pathCache = /* @__PURE__ */ new Map();
|
|
12
|
+
// name -> import path
|
|
13
|
+
this.loaderCache = /* @__PURE__ */ new Map();
|
|
12
14
|
this.baseDir = controllersDir;
|
|
13
15
|
this.mode = options?.mode ?? (process.env.WOOD_MODE === "development" ? "dev" : "bundled");
|
|
14
16
|
}
|
|
@@ -16,7 +18,20 @@ class ControllerResolver {
|
|
|
16
18
|
* Check whether a controller name has been pre-registered (class or path).
|
|
17
19
|
*/
|
|
18
20
|
has(name) {
|
|
19
|
-
return this.classCache.has(name) || this.pathCache.has(name);
|
|
21
|
+
return this.classCache.has(name) || this.pathCache.has(name) || this.loaderCache.has(name);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Register a lazy module loader for a controller. The loader is the
|
|
25
|
+
* CALLER's `() => import('...literal specifier...')`, so the import runs in
|
|
26
|
+
* the caller's module resolution (bundler/test-runner identity) instead of
|
|
27
|
+
* a raw filesystem import — same class identity as every other import of
|
|
28
|
+
* that module. Invoked only on first resolution.
|
|
29
|
+
*/
|
|
30
|
+
registerLoader(name, loader) {
|
|
31
|
+
if (typeof loader !== "function") {
|
|
32
|
+
throw new Error(`registerLoader("${name}"): expected a () => Promise<module> function`);
|
|
33
|
+
}
|
|
34
|
+
this.loaderCache.set(name, loader);
|
|
20
35
|
}
|
|
21
36
|
/**
|
|
22
37
|
* Register an import path for a controller. The controller will be lazily
|
|
@@ -41,6 +56,19 @@ class ControllerResolver {
|
|
|
41
56
|
async resolveClass(controllerName) {
|
|
42
57
|
const cached = this.classCache.get(controllerName);
|
|
43
58
|
if (cached) return cached;
|
|
59
|
+
const loader = this.loaderCache.get(controllerName);
|
|
60
|
+
if (loader) {
|
|
61
|
+
const mod = await loader();
|
|
62
|
+
const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];
|
|
63
|
+
if (!ControllerClass || typeof ControllerClass !== "function") {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Controller "${controllerName}": registered loader's module does not export a class`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
this.classCache.set(controllerName, ControllerClass);
|
|
69
|
+
logger.debug(`Resolved controller "${controllerName}" from registered loader`);
|
|
70
|
+
return ControllerClass;
|
|
71
|
+
}
|
|
44
72
|
const importPath = this.pathCache.get(controllerName);
|
|
45
73
|
if (importPath) {
|
|
46
74
|
const mod = await import(toImportSpecifier(importPath));
|
|
@@ -120,6 +148,22 @@ Registered controllers: [${Array.from(this.pathCache.keys()).join(", ")}]`
|
|
|
120
148
|
this.classCache.clear();
|
|
121
149
|
}
|
|
122
150
|
}
|
|
151
|
+
function usesOperationContext(ControllerClass) {
|
|
152
|
+
return ControllerClass?.woodContext === "operation";
|
|
153
|
+
}
|
|
154
|
+
function buildOperationContext(operation, ipcContext) {
|
|
155
|
+
const state = ipcContext.context ?? {};
|
|
156
|
+
return {
|
|
157
|
+
operation,
|
|
158
|
+
input: ipcContext.body,
|
|
159
|
+
state,
|
|
160
|
+
sender: ipcContext.sender,
|
|
161
|
+
windowId: ipcContext.windowId,
|
|
162
|
+
get(key) {
|
|
163
|
+
return state[key];
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
123
167
|
function buildControllerArgs(ipcContext, container) {
|
|
124
168
|
return {
|
|
125
169
|
req: {
|
|
@@ -144,6 +188,8 @@ function buildControllerArgs(ipcContext, container) {
|
|
|
144
188
|
}
|
|
145
189
|
export {
|
|
146
190
|
ControllerResolver,
|
|
147
|
-
buildControllerArgs
|
|
191
|
+
buildControllerArgs,
|
|
192
|
+
buildOperationContext,
|
|
193
|
+
usesOperationContext
|
|
148
194
|
};
|
|
149
195
|
//# sourceMappingURL=controller_resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/controller/controller_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport { getLogger } from '@noego/logger';\nimport type { IpcContext, ControllerArgs } from '../types/context.js';\n\nconst logger = getLogger('wood:controller');\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 ControllerResolver {\n private baseDir: string;\n private classCache = new Map<string, any>();\n private pathCache = new Map<string, string>(); // name -> import path\n private mode: 'bundled' | 'dev';\n\n constructor(controllersDir: string, options?: { mode?: 'bundled' | 'dev' }) {\n this.baseDir = controllersDir;\n // Default to bundled mode for safety. Dev mode must be explicitly opted into.\n this.mode = options?.mode ?? (process.env.WOOD_MODE === 'development' ? 'dev' : 'bundled');\n }\n\n /**\n * Check whether a controller name has been pre-registered (class or path).\n */\n has(name: string): boolean {\n return this.classCache.has(name) || this.pathCache.has(name);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed. This avoids circular dependencies\n * at module load time.\n */\n registerPath(name: string, importPath: string): void {\n if (!importPath) {\n throw new Error(`registerPath(\"${name}\"): importPath cannot be empty`);\n }\n this.pathCache.set(name, importPath);\n }\n\n /**\n * Resolve a controller name to its class.\n *\n * 1. Check class cache (already imported)\n * 2. Check path cache (registered via registerPath) and lazily import\n * 3. In dev mode only: fall back to filesystem resolution\n *\n * Classes are cached -- same class reference returned for same name.\n */\n async resolveClass(controllerName: string): Promise<any> {\n const cached = this.classCache.get(controllerName);\n if (cached) return cached;\n\n // Check if import path is registered — lazily load it\n const importPath = this.pathCache.get(controllerName);\n if (importPath) {\n const mod = await import(toImportSpecifier(importPath));\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\" at ${importPath}: module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered path`);\n return ControllerClass;\n }\n\n if (this.mode === 'bundled') {\n throw new Error(\n `Controller \"${controllerName}\" is not registered. ` +\n `In bundled mode, all controllers must be pre-registered via controllers.generated.ts. ` +\n `Run \"npx wood build\" to regenerate the registration file.\\n` +\n `Registered controllers: [${Array.from(this.pathCache.keys()).join(', ')}]`\n );\n }\n\n // Dev mode: attempt dynamic filesystem imports\n return this.resolveFromFilesystem(controllerName);\n }\n\n private async resolveFromFilesystem(controllerName: string): Promise<any> {\n const basePath = path.resolve(this.baseDir, controllerName);\n const candidates = [\n basePath + '.ts',\n basePath + '.controller.ts',\n basePath + '.js',\n basePath + '.controller.js',\n path.resolve(this.baseDir, controllerName, 'index.ts'),\n path.resolve(this.baseDir, controllerName, 'index.js'),\n ];\n\n let mod: any;\n let loaded = false;\n\n for (const candidate of candidates) {\n try {\n mod = await import(toImportSpecifier(candidate));\n loaded = true;\n break;\n } catch {\n // Try next candidate\n }\n }\n\n if (!loaded) {\n throw new Error(\n `Controller \"${controllerName}\" not found. Searched:\\n` +\n candidates.map(c => ` - ${c}`).join('\\n')\n );\n }\n\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": module does not export a class`\n );\n }\n\n logger.debug(`Resolved controller \"${controllerName}\" from ${this.baseDir}`);\n this.classCache.set(controllerName, ControllerClass);\n return ControllerClass;\n }\n\n /**\n * Create a controller instance using IoC container.\n * Per-request scoped: container.extend() creates an isolated scope.\n */\n async createInstance(ControllerClass: any, container: any): Promise<any> {\n const scopedContainer = container.extend();\n return scopedContainer.instance(ControllerClass);\n }\n\n /**\n * Pre-register a controller class by name so that resolveClass()\n * finds it in the cache without attempting a filesystem import.\n */\n register(name: string, ControllerClass: any): void {\n if (typeof ControllerClass !== 'function') {\n throw new Error(`register(\"${name}\"): expected a class/constructor, got ${typeof ControllerClass}`);\n }\n this.classCache.set(name, ControllerClass);\n }\n\n clearCache(): void {\n this.classCache.clear();\n }\n}\n\n/**\n * Build controller args from IPC context.\n * Creates a fake req/res that matches the Dinner web pattern so\n * existing controllers work without modification.\n */\nexport function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs {\n return {\n req: {\n body: ipcContext.body ?? {},\n params: ipcContext.params ?? {},\n query: ipcContext.query ?? {},\n context: ipcContext.context ?? {},\n headers: {},\n },\n res: {\n status: (_code: number) => {},\n cookie: (_name: string, _value: string, _opts?: unknown) => {},\n clearCookie: (_name: string, _opts?: unknown) => {},\n set: (_header: string, _value: string) => {},\n },\n container,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/controller/controller_resolver.ts"],"sourcesContent":["import path from 'path';\nimport { pathToFileURL } from 'node:url';\nimport { getLogger } from '@noego/logger';\nimport type { IpcContext, ControllerArgs } from '../types/context.js';\n\nconst logger = getLogger('wood:controller');\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 ControllerResolver {\n private baseDir: string;\n private classCache = new Map<string, any>();\n private pathCache = new Map<string, string>(); // name -> import path\n private loaderCache = new Map<string, () => Promise<unknown>>(); // name -> lazy module loader\n private mode: 'bundled' | 'dev';\n\n constructor(controllersDir: string, options?: { mode?: 'bundled' | 'dev' }) {\n this.baseDir = controllersDir;\n // Default to bundled mode for safety. Dev mode must be explicitly opted into.\n this.mode = options?.mode ?? (process.env.WOOD_MODE === 'development' ? 'dev' : 'bundled');\n }\n\n /**\n * Check whether a controller name has been pre-registered (class or path).\n */\n has(name: string): boolean {\n return this.classCache.has(name) || this.pathCache.has(name) || this.loaderCache.has(name);\n }\n\n /**\n * Register a lazy module loader for a controller. The loader is the\n * CALLER's `() => import('...literal specifier...')`, so the import runs in\n * the caller's module resolution (bundler/test-runner identity) instead of\n * a raw filesystem import — same class identity as every other import of\n * that module. Invoked only on first resolution.\n */\n registerLoader(name: string, loader: () => Promise<unknown>): void {\n if (typeof loader !== 'function') {\n throw new Error(`registerLoader(\"${name}\"): expected a () => Promise<module> function`);\n }\n this.loaderCache.set(name, loader);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed. This avoids circular dependencies\n * at module load time.\n */\n registerPath(name: string, importPath: string): void {\n if (!importPath) {\n throw new Error(`registerPath(\"${name}\"): importPath cannot be empty`);\n }\n this.pathCache.set(name, importPath);\n }\n\n /**\n * Resolve a controller name to its class.\n *\n * 1. Check class cache (already imported)\n * 2. Check path cache (registered via registerPath) and lazily import\n * 3. In dev mode only: fall back to filesystem resolution\n *\n * Classes are cached -- same class reference returned for same name.\n */\n async resolveClass(controllerName: string): Promise<any> {\n const cached = this.classCache.get(controllerName);\n if (cached) return cached;\n\n // Lazy loader (caller-owned import) takes precedence: it preserves the\n // caller's module identity for the controller and its dependency graph.\n const loader = this.loaderCache.get(controllerName);\n if (loader) {\n const mod = (await loader()) as Record<string, unknown>;\n const ControllerClass = (mod.default ?? mod[Object.keys(mod)[0]]) as unknown;\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": registered loader's module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered loader`);\n return ControllerClass;\n }\n\n // Check if import path is registered — lazily load it\n const importPath = this.pathCache.get(controllerName);\n if (importPath) {\n const mod = await import(toImportSpecifier(importPath));\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\" at ${importPath}: module does not export a class`\n );\n }\n this.classCache.set(controllerName, ControllerClass);\n logger.debug(`Resolved controller \"${controllerName}\" from registered path`);\n return ControllerClass;\n }\n\n if (this.mode === 'bundled') {\n throw new Error(\n `Controller \"${controllerName}\" is not registered. ` +\n `In bundled mode, all controllers must be pre-registered via controllers.generated.ts. ` +\n `Run \"npx wood build\" to regenerate the registration file.\\n` +\n `Registered controllers: [${Array.from(this.pathCache.keys()).join(', ')}]`\n );\n }\n\n // Dev mode: attempt dynamic filesystem imports\n return this.resolveFromFilesystem(controllerName);\n }\n\n private async resolveFromFilesystem(controllerName: string): Promise<any> {\n const basePath = path.resolve(this.baseDir, controllerName);\n const candidates = [\n basePath + '.ts',\n basePath + '.controller.ts',\n basePath + '.js',\n basePath + '.controller.js',\n path.resolve(this.baseDir, controllerName, 'index.ts'),\n path.resolve(this.baseDir, controllerName, 'index.js'),\n ];\n\n let mod: any;\n let loaded = false;\n\n for (const candidate of candidates) {\n try {\n mod = await import(toImportSpecifier(candidate));\n loaded = true;\n break;\n } catch {\n // Try next candidate\n }\n }\n\n if (!loaded) {\n throw new Error(\n `Controller \"${controllerName}\" not found. Searched:\\n` +\n candidates.map(c => ` - ${c}`).join('\\n')\n );\n }\n\n const ControllerClass = mod.default ?? mod[Object.keys(mod)[0]];\n if (!ControllerClass || typeof ControllerClass !== 'function') {\n throw new Error(\n `Controller \"${controllerName}\": module does not export a class`\n );\n }\n\n logger.debug(`Resolved controller \"${controllerName}\" from ${this.baseDir}`);\n this.classCache.set(controllerName, ControllerClass);\n return ControllerClass;\n }\n\n /**\n * Create a controller instance using IoC container.\n * Per-request scoped: container.extend() creates an isolated scope.\n */\n async createInstance(ControllerClass: any, container: any): Promise<any> {\n const scopedContainer = container.extend();\n return scopedContainer.instance(ControllerClass);\n }\n\n /**\n * Pre-register a controller class by name so that resolveClass()\n * finds it in the cache without attempting a filesystem import.\n */\n register(name: string, ControllerClass: any): void {\n if (typeof ControllerClass !== 'function') {\n throw new Error(`register(\"${name}\"): expected a class/constructor, got ${typeof ControllerClass}`);\n }\n this.classCache.set(name, ControllerClass);\n }\n\n clearCache(): void {\n this.classCache.clear();\n }\n}\n\n/**\n * Whether a controller class opted into the native Desktop boundary\n * (`static woodContext = 'operation'`). Native actions receive a\n * WoodOperationContext; everything else keeps the legacy args pair.\n */\nexport function usesOperationContext(ControllerClass: unknown): boolean {\n return (ControllerClass as { woodContext?: string })?.woodContext === 'operation';\n}\n\n/**\n * Build the native Wood operation context for a controller action.\n * Desktop-shaped: operation identity, validated input, middleware state,\n * sender/window — no fabricated HTTP surface, no container.\n */\nexport function buildOperationContext(\n operation: string,\n ipcContext: IpcContext\n): import('../types/context.js').WoodOperationContext {\n const state = ipcContext.context ?? {};\n return {\n operation,\n input: ipcContext.body,\n state,\n sender: ipcContext.sender,\n windowId: ipcContext.windowId,\n get<T>(key: string): T | undefined {\n return state[key] as T | undefined;\n },\n };\n}\n\n/**\n * Build controller args from IPC context.\n * LEGACY-COMPAT: creates a fake req/res matching the Dinner web pattern so\n * pre-native controllers work without modification. New controllers declare\n * `static woodContext = 'operation'` and receive a WoodOperationContext\n * (see buildOperationContext) instead.\n */\nexport function buildControllerArgs(ipcContext: IpcContext, container: unknown): ControllerArgs {\n return {\n req: {\n body: ipcContext.body ?? {},\n params: ipcContext.params ?? {},\n query: ipcContext.query ?? {},\n context: ipcContext.context ?? {},\n headers: {},\n },\n res: {\n status: (_code: number) => {},\n cookie: (_name: string, _value: string, _opts?: unknown) => {},\n clearCookie: (_name: string, _opts?: unknown) => {},\n set: (_header: string, _value: string) => {},\n },\n container,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -20,7 +20,9 @@ var controller_exports = {};
|
|
|
20
20
|
__export(controller_exports, {
|
|
21
21
|
ControllerResolver: () => import_controller_resolver.ControllerResolver,
|
|
22
22
|
buildControllerArgs: () => import_controller_resolver.buildControllerArgs,
|
|
23
|
-
|
|
23
|
+
buildOperationContext: () => import_controller_resolver.buildOperationContext,
|
|
24
|
+
disposeControllerLifecycle: () => import_controller_lifecycle.disposeControllerLifecycle,
|
|
25
|
+
usesOperationContext: () => import_controller_resolver.usesOperationContext
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(controller_exports);
|
|
26
28
|
var import_controller_resolver = require("./controller_resolver.cjs");
|
|
@@ -29,6 +31,8 @@ var import_controller_lifecycle = require("./controller_lifecycle.cjs");
|
|
|
29
31
|
0 && (module.exports = {
|
|
30
32
|
ControllerResolver,
|
|
31
33
|
buildControllerArgs,
|
|
32
|
-
|
|
34
|
+
buildOperationContext,
|
|
35
|
+
disposeControllerLifecycle,
|
|
36
|
+
usesOperationContext
|
|
33
37
|
});
|
|
34
38
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/controller/index.ts"],"sourcesContent":["export { ControllerResolver, buildControllerArgs } from './controller_resolver.cjs';\nexport type { ControllerLifecycle } from './controller_lifecycle.cjs';\nexport { disposeControllerLifecycle } from './controller_lifecycle.cjs';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/controller/index.ts"],"sourcesContent":["export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from './controller_resolver.cjs';\nexport type { ControllerLifecycle } from './controller_lifecycle.cjs';\nexport { disposeControllerLifecycle } from './controller_lifecycle.cjs';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAqG;AAErG,kCAA2C;","names":[]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ControllerResolver, buildControllerArgs } from './controller_resolver.cjs';
|
|
1
|
+
export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from './controller_resolver.cjs';
|
|
2
2
|
export { ControllerLifecycle, disposeControllerLifecycle } from './controller_lifecycle.cjs';
|
|
3
3
|
import '../types/context.cjs';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ControllerResolver, buildControllerArgs } from './controller_resolver.js';
|
|
1
|
+
export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from './controller_resolver.js';
|
|
2
2
|
export { ControllerLifecycle, disposeControllerLifecycle } from './controller_lifecycle.js';
|
|
3
3
|
import '../types/context.js';
|
package/dist/controller/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { ControllerResolver, buildControllerArgs } from "./controller_resolver.js";
|
|
1
|
+
import { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from "./controller_resolver.js";
|
|
2
2
|
import { disposeControllerLifecycle } from "./controller_lifecycle.js";
|
|
3
3
|
export {
|
|
4
4
|
ControllerResolver,
|
|
5
5
|
buildControllerArgs,
|
|
6
|
-
|
|
6
|
+
buildOperationContext,
|
|
7
|
+
disposeControllerLifecycle,
|
|
8
|
+
usesOperationContext
|
|
7
9
|
};
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/controller/index.ts"],"sourcesContent":["export { ControllerResolver, buildControllerArgs } from './controller_resolver.js';\nexport type { ControllerLifecycle } from './controller_lifecycle.js';\nexport { disposeControllerLifecycle } from './controller_lifecycle.js';\n"],"mappings":"AAAA,SAAS,oBAAoB,
|
|
1
|
+
{"version":3,"sources":["../../src/controller/index.ts"],"sourcesContent":["export { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from './controller_resolver.js';\nexport type { ControllerLifecycle } from './controller_lifecycle.js';\nexport { disposeControllerLifecycle } from './controller_lifecycle.js';\n"],"mappings":"AAAA,SAAS,oBAAoB,qBAAqB,uBAAuB,4BAA4B;AAErG,SAAS,kCAAkC;","names":[]}
|
|
@@ -88,7 +88,9 @@ class WoodDevServer {
|
|
|
88
88
|
logger.info("views parsed", { count: views.length });
|
|
89
89
|
const outDir = import_path.default.resolve(this.cwd, this.config.outDir);
|
|
90
90
|
(0, import_fs.mkdirSync)(outDir, { recursive: true });
|
|
91
|
-
const preloadCode = (0, import_preload_generator.generatePreload)(operations
|
|
91
|
+
const preloadCode = (0, import_preload_generator.generatePreload)(operations, {
|
|
92
|
+
traceBatching: (0, import_config_parser.resolveRendererTraceBatching)(this.config)
|
|
93
|
+
});
|
|
92
94
|
(0, import_fs.writeFileSync)(import_path.default.join(outDir, "preload.generated.ts"), preloadCode);
|
|
93
95
|
const typesCode = (0, import_type_generator.generateTypes)(operations);
|
|
94
96
|
(0, import_fs.writeFileSync)(import_path.default.join(outDir, "wood.d.ts"), typesCode);
|
|
@@ -191,6 +193,7 @@ class WoodDevServer {
|
|
|
191
193
|
outDir,
|
|
192
194
|
rendererOutDir: import_path.default.resolve(this.cwd, this.config.renderer.componentDir, "generated"),
|
|
193
195
|
cwd: this.cwd,
|
|
196
|
+
traceBatching: (0, import_config_parser.resolveRendererTraceBatching)(this.config),
|
|
194
197
|
onViewsChange: async () => {
|
|
195
198
|
const viewsContent = (0, import_fs.readFileSync)(
|
|
196
199
|
import_path.default.resolve(this.cwd, this.config.renderer.openapi),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/dev/wood_dev_server.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport path from 'path';\nimport { getLogger } from '@noego/logger';\nimport { parseConfig } from '../config/config_parser.cjs';\nimport { parseOperations } from '../parser/operations_parser.cjs';\nimport { parseViews } from '../parser/views_parser.cjs';\nimport { generatePreload } from '../codegen/preload_generator.cjs';\nimport { generateTypes } from '../codegen/type_generator.cjs';\nimport { generateTestMock } from '../codegen/test_mock_generator.cjs';\nimport { generateControllerRegistration } from '../codegen/controller_registration_generator.cjs';\nimport { generateRuntime } from '../codegen/runtime_generator.cjs';\nimport { generateRendererApp } from '../codegen/renderer_app_generator.cjs';\nimport { BackendBridge } from '../bridge/backend_bridge.cjs';\nimport { BackendWatcher } from './backend_watcher.cjs';\nimport { YamlWatcher } from './yaml_watcher.cjs';\nimport { EsbuildBackend } from './esbuild_backend.cjs';\nimport type { WoodConfig } from '../types/index.cjs';\n\nconst logger = getLogger('wood:dev');\n\nexport interface DevServerOptions {\n configPath?: string;\n cwd?: string;\n}\n\nexport class WoodDevServer {\n private config: WoodConfig | null = null;\n private bridge: BackendBridge | null = null;\n private backendWatcher: BackendWatcher | null = null;\n private yamlWatcher: YamlWatcher | null = null;\n private esbuild: EsbuildBackend | null = null;\n private cwd: string;\n\n constructor(options: DevServerOptions = {}) {\n this.cwd = options.cwd ?? process.cwd();\n }\n\n /**\n * Start the Wood development server.\n *\n * Automatically sets process.env.WOOD_MODE = 'development' so the app\n * can conditionally use dynamic controller imports (dev) vs pre-registered\n * controllers from the generated file (production).\n *\n * Steps:\n * 1. Parse config\n * 2. Parse + stitch YAML\n * 3. Generate preload, types, mock\n * 4. Build backend with esbuild\n * 5. (electron-vite would be started here -- omitted for MVP)\n * 6. Spawn backend via bridge\n * 7. Start watchers\n */\n async start(): Promise<void> {\n process.env.WOOD_MODE = 'development';\n\n // 1. Parse config\n const configPath = path.resolve(this.cwd, 'wood.config.yml');\n this.config = parseConfig(configPath);\n logger.info('config loaded', { outDir: this.config.outDir });\n\n // 2. Parse operations YAML\n const opsYamlPath = path.resolve(this.cwd, this.config.main.openapi);\n const opsContent = readFileSync(opsYamlPath, 'utf-8');\n const operations = parseOperations(opsContent);\n logger.info('operations parsed', { count: operations.size });\n\n // 3. Parse views YAML\n const viewsYamlPath = path.resolve(this.cwd, this.config.renderer.openapi);\n const viewsContent = readFileSync(viewsYamlPath, 'utf-8');\n const views = parseViews(viewsContent);\n logger.info('views parsed', { count: views.length });\n\n // 4. Generate files\n const outDir = path.resolve(this.cwd, this.config.outDir);\n mkdirSync(outDir, { recursive: true });\n\n const preloadCode = generatePreload(operations);\n writeFileSync(path.join(outDir, 'preload.generated.ts'), preloadCode);\n\n const typesCode = generateTypes(operations);\n writeFileSync(path.join(outDir, 'wood.d.ts'), typesCode);\n\n const mockCode = generateTestMock(operations);\n writeFileSync(path.join(outDir, 'wood.mock.ts'), mockCode);\n\n const controllersDir = path.resolve(this.cwd, this.config.main.controllers);\n const controllerRegCode = generateControllerRegistration(operations, {\n controllersDir,\n outDir,\n });\n writeFileSync(path.join(outDir, 'controllers.generated.ts'), controllerRegCode);\n\n const runtimeCode = generateRuntime(operations, {\n controllersDir,\n outDir,\n });\n writeFileSync(path.join(outDir, 'runtime.generated.ts'), runtimeCode);\n\n const rendererComponentDir = path.resolve(this.cwd, this.config.renderer.componentDir);\n const rendererOutDir = path.resolve(this.cwd, this.config.renderer.componentDir, 'generated');\n mkdirSync(rendererOutDir, { recursive: true });\n\n writeFileSync(path.join(rendererOutDir, 'wood.d.ts'), typesCode);\n\n writeFileSync(\n path.join(rendererOutDir, 'app.ts'),\n generateRendererApp(views, {\n componentDir: rendererComponentDir,\n outDir: rendererOutDir,\n entryViewKey: this.config.renderer.entry,\n }),\n );\n\n logger.info('codegen complete', { outDir });\n\n // 5. Build backend with esbuild (initial build + create incremental context)\n const backendEntry = this.config.main.entry;\n const backendOutfile = path.join(this.config.outDir, 'backend', 'index.js');\n\n this.esbuild = new EsbuildBackend({\n entryPoint: backendEntry,\n outfile: backendOutfile,\n cwd: this.cwd,\n external: this.config.build ? [] : undefined,\n });\n\n await this.esbuild.build();\n await this.esbuild.createContext();\n\n // 6. Start backend bridge (split-serve)\n if (this.config.dev?.splitServe !== false) {\n const resolvedBackendEntry = path.resolve(this.cwd, backendOutfile);\n this.bridge = new BackendBridge({\n backendEntry: resolvedBackendEntry,\n onReady: () => {\n logger.info('backend ready (split-serve)');\n },\n onPush: (channel, data) => {\n logger.debug('backend push', { channel, data });\n },\n onExit: (code, signal) => {\n logger.debug('backend exited', { code, signal });\n },\n });\n await this.bridge.start();\n }\n\n // 7. Start watchers\n if (this.config.dev?.watch !== false) {\n this.startWatchers(outDir);\n }\n }\n\n /** Stop the dev server and clean up all resources. */\n async stop(): Promise<void> {\n this.backendWatcher?.stop();\n this.yamlWatcher?.stop();\n\n if (this.bridge) {\n await this.bridge.stop();\n logger.info('backend bridge stopped');\n }\n\n if (this.esbuild) {\n await this.esbuild.dispose();\n }\n }\n\n /** Get the parsed config. */\n getConfig(): WoodConfig | null {\n return this.config;\n }\n\n private startWatchers(outDir: string): void {\n if (!this.config) return;\n\n // Backend watcher: server + middleware files -> rebuild + restart\n if (this.bridge && this.esbuild) {\n const backendPatterns = [\n `${this.config.main.controllers}/**/*.ts`,\n `${this.config.main.middleware}/**/*.ts`,\n `${this.config.main.entry}`,\n ...(this.config.main.watch ?? []),\n ];\n\n const esbuild = this.esbuild;\n this.backendWatcher = new BackendWatcher({\n patterns: backendPatterns,\n bridge: this.bridge,\n buildFn: () => esbuild.rebuild().then(() => {}),\n cwd: this.cwd,\n });\n this.backendWatcher.start();\n logger.info('backend watcher started', { patterns: backendPatterns });\n }\n\n // YAML watcher: operations + views YAML -> regenerate codegen\n this.yamlWatcher = new YamlWatcher({\n operationsYamlPath: this.config.main.openapi,\n viewsYamlPath: this.config.renderer.openapi,\n controllersDir: this.config.main.controllers,\n outDir,\n rendererOutDir: path.resolve(this.cwd, this.config.renderer.componentDir, 'generated'),\n cwd: this.cwd,\n onViewsChange: async () => {\n // Re-parse views and regenerate client router manifest\n const viewsContent = readFileSync(\n path.resolve(this.cwd, this.config!.renderer.openapi),\n 'utf-8',\n );\n const views = parseViews(viewsContent);\n\n const rendererComponentDir = path.resolve(this.cwd, this.config!.renderer.componentDir);\n const rendererOutDir = path.resolve(this.cwd, this.config!.renderer.componentDir, 'generated');\n mkdirSync(rendererOutDir, { recursive: true });\n\n writeFileSync(\n path.join(rendererOutDir, 'app.ts'),\n generateRendererApp(views, {\n componentDir: rendererComponentDir,\n outDir: rendererOutDir,\n entryViewKey: this.config!.renderer.entry,\n }),\n );\n\n logger.info('views renderer codegen regenerated', { rendererOutDir });\n },\n });\n this.yamlWatcher.start();\n logger.info('yaml watcher started');\n }\n}\n"],"mappings":"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","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/dev/wood_dev_server.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport path from 'path';\nimport { getLogger } from '@noego/logger';\nimport { parseConfig, resolveRendererTraceBatching } from '../config/config_parser.cjs';\nimport { parseOperations } from '../parser/operations_parser.cjs';\nimport { parseViews } from '../parser/views_parser.cjs';\nimport { generatePreload } from '../codegen/preload_generator.cjs';\nimport { generateTypes } from '../codegen/type_generator.cjs';\nimport { generateTestMock } from '../codegen/test_mock_generator.cjs';\nimport { generateControllerRegistration } from '../codegen/controller_registration_generator.cjs';\nimport { generateRuntime } from '../codegen/runtime_generator.cjs';\nimport { generateRendererApp } from '../codegen/renderer_app_generator.cjs';\nimport { BackendBridge } from '../bridge/backend_bridge.cjs';\nimport { BackendWatcher } from './backend_watcher.cjs';\nimport { YamlWatcher } from './yaml_watcher.cjs';\nimport { EsbuildBackend } from './esbuild_backend.cjs';\nimport type { WoodConfig } from '../types/index.cjs';\n\nconst logger = getLogger('wood:dev');\n\nexport interface DevServerOptions {\n configPath?: string;\n cwd?: string;\n}\n\nexport class WoodDevServer {\n private config: WoodConfig | null = null;\n private bridge: BackendBridge | null = null;\n private backendWatcher: BackendWatcher | null = null;\n private yamlWatcher: YamlWatcher | null = null;\n private esbuild: EsbuildBackend | null = null;\n private cwd: string;\n\n constructor(options: DevServerOptions = {}) {\n this.cwd = options.cwd ?? process.cwd();\n }\n\n /**\n * Start the Wood development server.\n *\n * Automatically sets process.env.WOOD_MODE = 'development' so the app\n * can conditionally use dynamic controller imports (dev) vs pre-registered\n * controllers from the generated file (production).\n *\n * Steps:\n * 1. Parse config\n * 2. Parse + stitch YAML\n * 3. Generate preload, types, mock\n * 4. Build backend with esbuild\n * 5. (electron-vite would be started here -- omitted for MVP)\n * 6. Spawn backend via bridge\n * 7. Start watchers\n */\n async start(): Promise<void> {\n process.env.WOOD_MODE = 'development';\n\n // 1. Parse config\n const configPath = path.resolve(this.cwd, 'wood.config.yml');\n this.config = parseConfig(configPath);\n logger.info('config loaded', { outDir: this.config.outDir });\n\n // 2. Parse operations YAML\n const opsYamlPath = path.resolve(this.cwd, this.config.main.openapi);\n const opsContent = readFileSync(opsYamlPath, 'utf-8');\n const operations = parseOperations(opsContent);\n logger.info('operations parsed', { count: operations.size });\n\n // 3. Parse views YAML\n const viewsYamlPath = path.resolve(this.cwd, this.config.renderer.openapi);\n const viewsContent = readFileSync(viewsYamlPath, 'utf-8');\n const views = parseViews(viewsContent);\n logger.info('views parsed', { count: views.length });\n\n // 4. Generate files\n const outDir = path.resolve(this.cwd, this.config.outDir);\n mkdirSync(outDir, { recursive: true });\n\n const preloadCode = generatePreload(operations, {\n traceBatching: resolveRendererTraceBatching(this.config),\n });\n writeFileSync(path.join(outDir, 'preload.generated.ts'), preloadCode);\n\n const typesCode = generateTypes(operations);\n writeFileSync(path.join(outDir, 'wood.d.ts'), typesCode);\n\n const mockCode = generateTestMock(operations);\n writeFileSync(path.join(outDir, 'wood.mock.ts'), mockCode);\n\n const controllersDir = path.resolve(this.cwd, this.config.main.controllers);\n const controllerRegCode = generateControllerRegistration(operations, {\n controllersDir,\n outDir,\n });\n writeFileSync(path.join(outDir, 'controllers.generated.ts'), controllerRegCode);\n\n const runtimeCode = generateRuntime(operations, {\n controllersDir,\n outDir,\n });\n writeFileSync(path.join(outDir, 'runtime.generated.ts'), runtimeCode);\n\n const rendererComponentDir = path.resolve(this.cwd, this.config.renderer.componentDir);\n const rendererOutDir = path.resolve(this.cwd, this.config.renderer.componentDir, 'generated');\n mkdirSync(rendererOutDir, { recursive: true });\n\n writeFileSync(path.join(rendererOutDir, 'wood.d.ts'), typesCode);\n\n writeFileSync(\n path.join(rendererOutDir, 'app.ts'),\n generateRendererApp(views, {\n componentDir: rendererComponentDir,\n outDir: rendererOutDir,\n entryViewKey: this.config.renderer.entry,\n }),\n );\n\n logger.info('codegen complete', { outDir });\n\n // 5. Build backend with esbuild (initial build + create incremental context)\n const backendEntry = this.config.main.entry;\n const backendOutfile = path.join(this.config.outDir, 'backend', 'index.js');\n\n this.esbuild = new EsbuildBackend({\n entryPoint: backendEntry,\n outfile: backendOutfile,\n cwd: this.cwd,\n external: this.config.build ? [] : undefined,\n });\n\n await this.esbuild.build();\n await this.esbuild.createContext();\n\n // 6. Start backend bridge (split-serve)\n if (this.config.dev?.splitServe !== false) {\n const resolvedBackendEntry = path.resolve(this.cwd, backendOutfile);\n this.bridge = new BackendBridge({\n backendEntry: resolvedBackendEntry,\n onReady: () => {\n logger.info('backend ready (split-serve)');\n },\n onPush: (channel, data) => {\n logger.debug('backend push', { channel, data });\n },\n onExit: (code, signal) => {\n logger.debug('backend exited', { code, signal });\n },\n });\n await this.bridge.start();\n }\n\n // 7. Start watchers\n if (this.config.dev?.watch !== false) {\n this.startWatchers(outDir);\n }\n }\n\n /** Stop the dev server and clean up all resources. */\n async stop(): Promise<void> {\n this.backendWatcher?.stop();\n this.yamlWatcher?.stop();\n\n if (this.bridge) {\n await this.bridge.stop();\n logger.info('backend bridge stopped');\n }\n\n if (this.esbuild) {\n await this.esbuild.dispose();\n }\n }\n\n /** Get the parsed config. */\n getConfig(): WoodConfig | null {\n return this.config;\n }\n\n private startWatchers(outDir: string): void {\n if (!this.config) return;\n\n // Backend watcher: server + middleware files -> rebuild + restart\n if (this.bridge && this.esbuild) {\n const backendPatterns = [\n `${this.config.main.controllers}/**/*.ts`,\n `${this.config.main.middleware}/**/*.ts`,\n `${this.config.main.entry}`,\n ...(this.config.main.watch ?? []),\n ];\n\n const esbuild = this.esbuild;\n this.backendWatcher = new BackendWatcher({\n patterns: backendPatterns,\n bridge: this.bridge,\n buildFn: () => esbuild.rebuild().then(() => {}),\n cwd: this.cwd,\n });\n this.backendWatcher.start();\n logger.info('backend watcher started', { patterns: backendPatterns });\n }\n\n // YAML watcher: operations + views YAML -> regenerate codegen\n this.yamlWatcher = new YamlWatcher({\n operationsYamlPath: this.config.main.openapi,\n viewsYamlPath: this.config.renderer.openapi,\n controllersDir: this.config.main.controllers,\n outDir,\n rendererOutDir: path.resolve(this.cwd, this.config.renderer.componentDir, 'generated'),\n cwd: this.cwd,\n traceBatching: resolveRendererTraceBatching(this.config),\n onViewsChange: async () => {\n // Re-parse views and regenerate client router manifest\n const viewsContent = readFileSync(\n path.resolve(this.cwd, this.config!.renderer.openapi),\n 'utf-8',\n );\n const views = parseViews(viewsContent);\n\n const rendererComponentDir = path.resolve(this.cwd, this.config!.renderer.componentDir);\n const rendererOutDir = path.resolve(this.cwd, this.config!.renderer.componentDir, 'generated');\n mkdirSync(rendererOutDir, { recursive: true });\n\n writeFileSync(\n path.join(rendererOutDir, 'app.ts'),\n generateRendererApp(views, {\n componentDir: rendererComponentDir,\n outDir: rendererOutDir,\n entryViewKey: this.config!.renderer.entry,\n }),\n );\n\n logger.info('views renderer codegen regenerated', { rendererOutDir });\n },\n });\n this.yamlWatcher.start();\n logger.info('yaml watcher started');\n }\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { getLogger } from "@noego/logger";
|
|
4
|
-
import { parseConfig } from "../config/config_parser.js";
|
|
4
|
+
import { parseConfig, resolveRendererTraceBatching } from "../config/config_parser.js";
|
|
5
5
|
import { parseOperations } from "../parser/operations_parser.js";
|
|
6
6
|
import { parseViews } from "../parser/views_parser.js";
|
|
7
7
|
import { generatePreload } from "../codegen/preload_generator.js";
|
|
@@ -55,7 +55,9 @@ class WoodDevServer {
|
|
|
55
55
|
logger.info("views parsed", { count: views.length });
|
|
56
56
|
const outDir = path.resolve(this.cwd, this.config.outDir);
|
|
57
57
|
mkdirSync(outDir, { recursive: true });
|
|
58
|
-
const preloadCode = generatePreload(operations
|
|
58
|
+
const preloadCode = generatePreload(operations, {
|
|
59
|
+
traceBatching: resolveRendererTraceBatching(this.config)
|
|
60
|
+
});
|
|
59
61
|
writeFileSync(path.join(outDir, "preload.generated.ts"), preloadCode);
|
|
60
62
|
const typesCode = generateTypes(operations);
|
|
61
63
|
writeFileSync(path.join(outDir, "wood.d.ts"), typesCode);
|
|
@@ -158,6 +160,7 @@ class WoodDevServer {
|
|
|
158
160
|
outDir,
|
|
159
161
|
rendererOutDir: path.resolve(this.cwd, this.config.renderer.componentDir, "generated"),
|
|
160
162
|
cwd: this.cwd,
|
|
163
|
+
traceBatching: resolveRendererTraceBatching(this.config),
|
|
161
164
|
onViewsChange: async () => {
|
|
162
165
|
const viewsContent = readFileSync(
|
|
163
166
|
path.resolve(this.cwd, this.config.renderer.openapi),
|