@noego/wood 0.4.10 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -42
- 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 +18 -3
- package/dist/client/index.d.ts +18 -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 +78 -42
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +78 -42
- 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 +10 -7
- package/dist/index.d.ts +10 -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/index.cjs +3 -0
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +25 -1
- package/dist/navigation/index.d.ts +25 -1
- package/dist/navigation/index.js +2 -0
- 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/browser.cjs +104 -23
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +8 -3
- package/dist/testing/browser.d.ts +8 -3
- package/dist/testing/browser.js +102 -22
- 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 +17 -2
- package/dist/testing/create_controller_harness.d.ts +17 -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/index.cjs +31 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +20 -5
- package/dist/testing/index.d.ts +20 -5
- package/dist/testing/index.js +19 -1
- 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 +13 -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 +0 -29
- 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 +0 -27
- 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 +0 -27
- 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 +0 -47
- 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
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { WoodConfig } from '../types/config.cjs';
|
|
1
|
+
import { RendererTraceBatchingConfig, WoodConfig } from '../types/config.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parse and validate a wood.config.yml file, returning a fully-typed WoodConfig
|
|
5
5
|
* with defaults applied for optional fields.
|
|
6
6
|
*/
|
|
7
7
|
declare function parseConfig(configPath: string): WoodConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Default renderer→main IPC trace batching policy. These values match the
|
|
10
|
+
* policy previously hard-coded in the generated preload; wood.config.yml
|
|
11
|
+
* `observability.trace.rendererToMain.batching` is now the owner.
|
|
12
|
+
*/
|
|
13
|
+
declare const RENDERER_TRACE_BATCHING_DEFAULTS: RendererTraceBatchingConfig;
|
|
14
|
+
/** Resolves the renderer trace batching policy from a parsed config. */
|
|
15
|
+
declare function resolveRendererTraceBatching(config: Pick<WoodConfig, 'observability'>): RendererTraceBatchingConfig;
|
|
8
16
|
|
|
9
|
-
export { parseConfig };
|
|
17
|
+
export { RENDERER_TRACE_BATCHING_DEFAULTS, parseConfig, resolveRendererTraceBatching };
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { WoodConfig } from '../types/config.js';
|
|
1
|
+
import { RendererTraceBatchingConfig, WoodConfig } from '../types/config.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parse and validate a wood.config.yml file, returning a fully-typed WoodConfig
|
|
5
5
|
* with defaults applied for optional fields.
|
|
6
6
|
*/
|
|
7
7
|
declare function parseConfig(configPath: string): WoodConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Default renderer→main IPC trace batching policy. These values match the
|
|
10
|
+
* policy previously hard-coded in the generated preload; wood.config.yml
|
|
11
|
+
* `observability.trace.rendererToMain.batching` is now the owner.
|
|
12
|
+
*/
|
|
13
|
+
declare const RENDERER_TRACE_BATCHING_DEFAULTS: RendererTraceBatchingConfig;
|
|
14
|
+
/** Resolves the renderer trace batching policy from a parsed config. */
|
|
15
|
+
declare function resolveRendererTraceBatching(config: Pick<WoodConfig, 'observability'>): RendererTraceBatchingConfig;
|
|
8
16
|
|
|
9
|
-
export { parseConfig };
|
|
17
|
+
export { RENDERER_TRACE_BATCHING_DEFAULTS, parseConfig, resolveRendererTraceBatching };
|
|
@@ -79,6 +79,23 @@ function requireNumber(_doc, field, value) {
|
|
|
79
79
|
throw new Error(`Config validation error: "${field}" is required and must be a number`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
function parseTestingSection(section, raw, allowedKeys) {
|
|
83
|
+
if (raw === void 0) return {};
|
|
84
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
85
|
+
throw new Error(`Config validation error: "${section}.testing" must be an object`);
|
|
86
|
+
}
|
|
87
|
+
const testing = {};
|
|
88
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
89
|
+
if (!allowedKeys.includes(key)) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Config validation error: "${section}.testing.${key}" is not a known hook (allowed: ${allowedKeys.join(", ")})`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
requireString(raw, `${section}.testing.${key}`, value);
|
|
95
|
+
testing[key] = value;
|
|
96
|
+
}
|
|
97
|
+
return { testing };
|
|
98
|
+
}
|
|
82
99
|
function applyDefaults(doc) {
|
|
83
100
|
const app = doc.app;
|
|
84
101
|
const main = doc.main;
|
|
@@ -107,14 +124,16 @@ function applyDefaults(doc) {
|
|
|
107
124
|
controllers: main.controllers,
|
|
108
125
|
middleware: main.middleware,
|
|
109
126
|
openapi: main.openapi,
|
|
110
|
-
watch: Array.isArray(main.watch) ? main.watch : []
|
|
127
|
+
watch: Array.isArray(main.watch) ? main.watch : [],
|
|
128
|
+
...parseTestingSection("main", main.testing, ["compose"])
|
|
111
129
|
},
|
|
112
130
|
renderer: {
|
|
113
131
|
openapi: renderer.openapi,
|
|
114
132
|
componentDir: renderer.componentDir,
|
|
115
133
|
controllers: renderer.controllers,
|
|
116
134
|
...typeof renderer.entry === "string" ? { entry: renderer.entry } : {},
|
|
117
|
-
...Array.isArray(renderer.watch) ? { watch: renderer.watch } : {}
|
|
135
|
+
...Array.isArray(renderer.watch) ? { watch: renderer.watch } : {},
|
|
136
|
+
...parseTestingSection("renderer", renderer.testing, ["host"])
|
|
118
137
|
},
|
|
119
138
|
windows,
|
|
120
139
|
dev
|
|
@@ -134,9 +153,79 @@ function applyDefaults(doc) {
|
|
|
134
153
|
if (doc.build && typeof doc.build === "object") {
|
|
135
154
|
config.build = doc.build;
|
|
136
155
|
}
|
|
156
|
+
if (doc.observability && typeof doc.observability === "object") {
|
|
157
|
+
config.observability = parseObservability(doc.observability);
|
|
158
|
+
}
|
|
137
159
|
return config;
|
|
138
160
|
}
|
|
161
|
+
const RENDERER_TRACE_BATCHING_DEFAULTS = Object.freeze({
|
|
162
|
+
maxQueuedEvents: 256,
|
|
163
|
+
maxBatchEvents: 32,
|
|
164
|
+
acknowledgementTimeoutMs: 1e3,
|
|
165
|
+
retryLimit: 3,
|
|
166
|
+
retryBaseDelayMs: 25
|
|
167
|
+
});
|
|
168
|
+
function resolveRendererTraceBatching(config) {
|
|
169
|
+
return {
|
|
170
|
+
...RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
171
|
+
...config.observability?.trace?.rendererToMain?.batching
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function parseObservability(raw) {
|
|
175
|
+
const trace = raw.trace;
|
|
176
|
+
if (trace === void 0) {
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
if (typeof trace !== "object" || trace === null) {
|
|
180
|
+
throw new Error('Config validation error: "observability.trace" must be an object');
|
|
181
|
+
}
|
|
182
|
+
const rendererToMain = trace.rendererToMain;
|
|
183
|
+
if (rendererToMain === void 0) {
|
|
184
|
+
return { trace: {} };
|
|
185
|
+
}
|
|
186
|
+
if (typeof rendererToMain !== "object" || rendererToMain === null) {
|
|
187
|
+
throw new Error('Config validation error: "observability.trace.rendererToMain" must be an object');
|
|
188
|
+
}
|
|
189
|
+
const batching = rendererToMain.batching;
|
|
190
|
+
if (batching === void 0) {
|
|
191
|
+
return { trace: { rendererToMain: {} } };
|
|
192
|
+
}
|
|
193
|
+
if (typeof batching !== "object" || batching === null) {
|
|
194
|
+
throw new Error('Config validation error: "observability.trace.rendererToMain.batching" must be an object');
|
|
195
|
+
}
|
|
196
|
+
const resolved = {
|
|
197
|
+
...RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
198
|
+
...batching
|
|
199
|
+
};
|
|
200
|
+
const positiveIntFields = ["maxQueuedEvents", "maxBatchEvents", "acknowledgementTimeoutMs"];
|
|
201
|
+
for (const field of positiveIntFields) {
|
|
202
|
+
const value = resolved[field];
|
|
203
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Config validation error: "observability.trace.rendererToMain.batching.${field}" must be a positive integer`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!Number.isSafeInteger(resolved.retryLimit) || resolved.retryLimit < 0) {
|
|
210
|
+
throw new Error(
|
|
211
|
+
'Config validation error: "observability.trace.rendererToMain.batching.retryLimit" must be a non-negative integer'
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
if (!Number.isFinite(resolved.retryBaseDelayMs) || resolved.retryBaseDelayMs < 0) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
'Config validation error: "observability.trace.rendererToMain.batching.retryBaseDelayMs" must be a non-negative number'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
if (resolved.maxBatchEvents > resolved.maxQueuedEvents) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
'Config validation error: "observability.trace.rendererToMain.batching.maxBatchEvents" cannot exceed maxQueuedEvents'
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
return { trace: { rendererToMain: { batching: resolved } } };
|
|
225
|
+
}
|
|
139
226
|
export {
|
|
140
|
-
|
|
227
|
+
RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
228
|
+
parseConfig,
|
|
229
|
+
resolveRendererTraceBatching
|
|
141
230
|
};
|
|
142
231
|
//# sourceMappingURL=config_parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/config_parser.ts"],"sourcesContent":["import yaml from 'js-yaml';\nimport { readFileSync, existsSync } from 'fs';\nimport path from 'path';\nimport { getLogger } from '@noego/logger';\nimport type { WoodConfig, WindowDef, DevConfig } from '../types/config.js';\n\nconst logger = getLogger('wood:config');\n\n/** Default values applied when optional fields are omitted. */\nconst WINDOW_DEFAULTS: Partial<WindowDef> = {\n frame: true,\n resizable: true,\n show: true,\n modal: false,\n};\n\nconst DEV_DEFAULTS: DevConfig = {\n watch: true,\n splitServe: true,\n port: 5173,\n};\n\n/**\n * Parse and validate a wood.config.yml file, returning a fully-typed WoodConfig\n * with defaults applied for optional fields.\n */\nexport function parseConfig(configPath: string): WoodConfig {\n const resolved = path.resolve(configPath);\n\n if (!existsSync(resolved)) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n\n const raw = readFileSync(resolved, 'utf-8');\n const doc = yaml.load(raw) as Record<string, unknown> | null;\n\n if (!doc || typeof doc !== 'object') {\n throw new Error(`Invalid YAML in config file: ${resolved}`);\n }\n\n validateRequired(doc);\n\n const config = applyDefaults(doc as RawConfig);\n\n logger.info('Parsed config', { path: resolved, windows: Object.keys(config.windows) });\n\n return config;\n}\n\n/** Shape of the raw YAML before defaults are applied. */\ntype RawConfig = Record<string, unknown>;\n\nfunction validateRequired(doc: Record<string, unknown>): void {\n requireString(doc, 'app.boot', (doc as Record<string, Record<string, unknown>>).app?.boot);\n requireString(doc, 'main.entry', (doc as Record<string, Record<string, unknown>>).main?.entry);\n requireString(doc, 'main.controllers', (doc as Record<string, Record<string, unknown>>).main?.controllers);\n requireString(doc, 'main.middleware', (doc as Record<string, Record<string, unknown>>).main?.middleware);\n requireString(doc, 'main.openapi', (doc as Record<string, Record<string, unknown>>).main?.openapi);\n requireString(doc, 'renderer.openapi', (doc as Record<string, Record<string, unknown>>).renderer?.openapi);\n requireString(doc, 'renderer.componentDir', (doc as Record<string, Record<string, unknown>>).renderer?.componentDir);\n requireString(doc, 'renderer.controllers', (doc as Record<string, Record<string, unknown>>).renderer?.controllers);\n const rendererEntry = (doc as Record<string, Record<string, unknown>>).renderer?.entry;\n if (rendererEntry !== undefined) {\n requireString(doc, 'renderer.entry', rendererEntry);\n }\n\n // Windows validation\n const windows = doc.windows;\n if (!windows || typeof windows !== 'object') {\n throw new Error('Config validation error: \"windows\" is required and must be an object with at least one window');\n }\n\n const windowKeys = Object.keys(windows as Record<string, unknown>);\n if (windowKeys.length === 0) {\n throw new Error('Config validation error: \"windows\" must contain at least one window definition');\n }\n\n for (const key of windowKeys) {\n const win = (windows as Record<string, Record<string, unknown>>)[key];\n if (!win || typeof win !== 'object') {\n throw new Error(`Config validation error: window \"${key}\" must be an object`);\n }\n requireString(doc, `windows.${key}.title`, win.title);\n requireNumber(doc, `windows.${key}.width`, win.width);\n requireNumber(doc, `windows.${key}.height`, win.height);\n requireString(doc, `windows.${key}.defaultRoute`, win.defaultRoute);\n\n if (win.contextMenu !== undefined) {\n if (typeof win.contextMenu !== 'string') {\n throw new Error(`Config validation error: \"windows.${key}.contextMenu\" must be a string`);\n }\n if (win.contextMenu !== 'native' && win.contextMenu !== 'custom') {\n throw new Error(`Config validation error: \"windows.${key}.contextMenu\" must be \"native\" or \"custom\"`);\n }\n }\n }\n}\n\nfunction requireString(_doc: Record<string, unknown>, field: string, value: unknown): asserts value is string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Config validation error: \"${field}\" is required and must be a non-empty string`);\n }\n}\n\nfunction requireNumber(_doc: Record<string, unknown>, field: string, value: unknown): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(`Config validation error: \"${field}\" is required and must be a number`);\n }\n}\n\nfunction applyDefaults(doc: RawConfig): WoodConfig {\n const app = doc.app as Record<string, unknown>;\n const main = doc.main as Record<string, unknown>;\n const renderer = doc.renderer as Record<string, unknown>;\n const rawWindows = doc.windows as Record<string, Record<string, unknown>>;\n\n const windows: Record<string, WindowDef> = {};\n for (const [key, rawWin] of Object.entries(rawWindows)) {\n windows[key] = {\n ...WINDOW_DEFAULTS,\n ...rawWin,\n } as WindowDef;\n }\n\n const dev: DevConfig = {\n ...DEV_DEFAULTS,\n ...(doc.dev as Record<string, unknown> | undefined),\n };\n\n const config: WoodConfig = {\n root: typeof doc.root === 'string' ? doc.root : '.',\n outDir: typeof doc.outDir === 'string' ? doc.outDir : 'dist',\n app: {\n boot: app.boot as string,\n watch: Array.isArray(app.watch) ? (app.watch as string[]) : [],\n },\n main: {\n entry: main.entry as string,\n controllers: main.controllers as string,\n middleware: main.middleware as string,\n openapi: main.openapi as string,\n watch: Array.isArray(main.watch) ? (main.watch as string[]) : [],\n },\n renderer: {\n openapi: renderer.openapi as string,\n componentDir: renderer.componentDir as string,\n controllers: renderer.controllers as string,\n ...(typeof renderer.entry === 'string' ? { entry: renderer.entry as string } : {}),\n ...(Array.isArray(renderer.watch) ? { watch: renderer.watch as string[] } : {}),\n },\n windows,\n dev,\n };\n\n // Optional database section (preserve :userData: token for runtime expansion)\n if (doc.database && typeof doc.database === 'object') {\n const db = doc.database as Record<string, unknown>;\n if (typeof db.path === 'string') {\n config.database = {\n path: db.path,\n ...(typeof db.migrations === 'string' ? { migrations: db.migrations } : {}),\n };\n }\n }\n\n // Optional assets\n if (Array.isArray(doc.assets)) {\n config.assets = doc.assets as string[];\n }\n\n // Optional build section\n if (doc.build && typeof doc.build === 'object') {\n config.build = doc.build as WoodConfig['build'];\n }\n\n return config;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/config_parser.ts"],"sourcesContent":["import yaml from 'js-yaml';\nimport { readFileSync, existsSync } from 'fs';\nimport path from 'path';\nimport { getLogger } from '@noego/logger';\nimport type {\n WoodConfig,\n WindowDef,\n DevConfig,\n RendererTraceBatchingConfig,\n} from '../types/config.js';\n\nconst logger = getLogger('wood:config');\n\n/** Default values applied when optional fields are omitted. */\nconst WINDOW_DEFAULTS: Partial<WindowDef> = {\n frame: true,\n resizable: true,\n show: true,\n modal: false,\n};\n\nconst DEV_DEFAULTS: DevConfig = {\n watch: true,\n splitServe: true,\n port: 5173,\n};\n\n/**\n * Parse and validate a wood.config.yml file, returning a fully-typed WoodConfig\n * with defaults applied for optional fields.\n */\nexport function parseConfig(configPath: string): WoodConfig {\n const resolved = path.resolve(configPath);\n\n if (!existsSync(resolved)) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n\n const raw = readFileSync(resolved, 'utf-8');\n const doc = yaml.load(raw) as Record<string, unknown> | null;\n\n if (!doc || typeof doc !== 'object') {\n throw new Error(`Invalid YAML in config file: ${resolved}`);\n }\n\n validateRequired(doc);\n\n const config = applyDefaults(doc as RawConfig);\n\n logger.info('Parsed config', { path: resolved, windows: Object.keys(config.windows) });\n\n return config;\n}\n\n/** Shape of the raw YAML before defaults are applied. */\ntype RawConfig = Record<string, unknown>;\n\nfunction validateRequired(doc: Record<string, unknown>): void {\n requireString(doc, 'app.boot', (doc as Record<string, Record<string, unknown>>).app?.boot);\n requireString(doc, 'main.entry', (doc as Record<string, Record<string, unknown>>).main?.entry);\n requireString(doc, 'main.controllers', (doc as Record<string, Record<string, unknown>>).main?.controllers);\n requireString(doc, 'main.middleware', (doc as Record<string, Record<string, unknown>>).main?.middleware);\n requireString(doc, 'main.openapi', (doc as Record<string, Record<string, unknown>>).main?.openapi);\n requireString(doc, 'renderer.openapi', (doc as Record<string, Record<string, unknown>>).renderer?.openapi);\n requireString(doc, 'renderer.componentDir', (doc as Record<string, Record<string, unknown>>).renderer?.componentDir);\n requireString(doc, 'renderer.controllers', (doc as Record<string, Record<string, unknown>>).renderer?.controllers);\n const rendererEntry = (doc as Record<string, Record<string, unknown>>).renderer?.entry;\n if (rendererEntry !== undefined) {\n requireString(doc, 'renderer.entry', rendererEntry);\n }\n\n // Windows validation\n const windows = doc.windows;\n if (!windows || typeof windows !== 'object') {\n throw new Error('Config validation error: \"windows\" is required and must be an object with at least one window');\n }\n\n const windowKeys = Object.keys(windows as Record<string, unknown>);\n if (windowKeys.length === 0) {\n throw new Error('Config validation error: \"windows\" must contain at least one window definition');\n }\n\n for (const key of windowKeys) {\n const win = (windows as Record<string, Record<string, unknown>>)[key];\n if (!win || typeof win !== 'object') {\n throw new Error(`Config validation error: window \"${key}\" must be an object`);\n }\n requireString(doc, `windows.${key}.title`, win.title);\n requireNumber(doc, `windows.${key}.width`, win.width);\n requireNumber(doc, `windows.${key}.height`, win.height);\n requireString(doc, `windows.${key}.defaultRoute`, win.defaultRoute);\n\n if (win.contextMenu !== undefined) {\n if (typeof win.contextMenu !== 'string') {\n throw new Error(`Config validation error: \"windows.${key}.contextMenu\" must be a string`);\n }\n if (win.contextMenu !== 'native' && win.contextMenu !== 'custom') {\n throw new Error(`Config validation error: \"windows.${key}.contextMenu\" must be \"native\" or \"custom\"`);\n }\n }\n }\n}\n\nfunction requireString(_doc: Record<string, unknown>, field: string, value: unknown): asserts value is string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Config validation error: \"${field}\" is required and must be a non-empty string`);\n }\n}\n\nfunction requireNumber(_doc: Record<string, unknown>, field: string, value: unknown): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(`Config validation error: \"${field}\" is required and must be a number`);\n }\n}\n\n/**\n * Parse an optional `<section>.testing` mapping: every allowed key is an\n * optional non-empty string (a config-relative module path); anything else\n * is a validation error so a typo cannot silently drop a hook.\n */\nfunction parseTestingSection(\n section: 'main' | 'renderer',\n raw: unknown,\n allowedKeys: readonly string[],\n): { testing?: Record<string, string> } {\n if (raw === undefined) return {};\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new Error(`Config validation error: \"${section}.testing\" must be an object`);\n }\n const testing: Record<string, string> = {};\n for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!allowedKeys.includes(key)) {\n throw new Error(\n `Config validation error: \"${section}.testing.${key}\" is not a known hook (allowed: ${allowedKeys.join(', ')})`,\n );\n }\n requireString(raw as Record<string, unknown>, `${section}.testing.${key}`, value);\n testing[key] = value;\n }\n return { testing };\n}\n\nfunction applyDefaults(doc: RawConfig): WoodConfig {\n const app = doc.app as Record<string, unknown>;\n const main = doc.main as Record<string, unknown>;\n const renderer = doc.renderer as Record<string, unknown>;\n const rawWindows = doc.windows as Record<string, Record<string, unknown>>;\n\n const windows: Record<string, WindowDef> = {};\n for (const [key, rawWin] of Object.entries(rawWindows)) {\n windows[key] = {\n ...WINDOW_DEFAULTS,\n ...rawWin,\n } as WindowDef;\n }\n\n const dev: DevConfig = {\n ...DEV_DEFAULTS,\n ...(doc.dev as Record<string, unknown> | undefined),\n };\n\n const config: WoodConfig = {\n root: typeof doc.root === 'string' ? doc.root : '.',\n outDir: typeof doc.outDir === 'string' ? doc.outDir : 'dist',\n app: {\n boot: app.boot as string,\n watch: Array.isArray(app.watch) ? (app.watch as string[]) : [],\n },\n main: {\n entry: main.entry as string,\n controllers: main.controllers as string,\n middleware: main.middleware as string,\n openapi: main.openapi as string,\n watch: Array.isArray(main.watch) ? (main.watch as string[]) : [],\n ...parseTestingSection('main', main.testing, ['compose']),\n },\n renderer: {\n openapi: renderer.openapi as string,\n componentDir: renderer.componentDir as string,\n controllers: renderer.controllers as string,\n ...(typeof renderer.entry === 'string' ? { entry: renderer.entry as string } : {}),\n ...(Array.isArray(renderer.watch) ? { watch: renderer.watch as string[] } : {}),\n ...parseTestingSection('renderer', renderer.testing, ['host']),\n },\n windows,\n dev,\n };\n\n // Optional database section (preserve :userData: token for runtime expansion)\n if (doc.database && typeof doc.database === 'object') {\n const db = doc.database as Record<string, unknown>;\n if (typeof db.path === 'string') {\n config.database = {\n path: db.path,\n ...(typeof db.migrations === 'string' ? { migrations: db.migrations } : {}),\n };\n }\n }\n\n // Optional assets\n if (Array.isArray(doc.assets)) {\n config.assets = doc.assets as string[];\n }\n\n // Optional build section\n if (doc.build && typeof doc.build === 'object') {\n config.build = doc.build as WoodConfig['build'];\n }\n\n // Optional observability section (renderer→main trace batching policy)\n if (doc.observability && typeof doc.observability === 'object') {\n config.observability = parseObservability(doc.observability as Record<string, unknown>);\n }\n\n return config;\n}\n\n/**\n * Default renderer→main IPC trace batching policy. These values match the\n * policy previously hard-coded in the generated preload; wood.config.yml\n * `observability.trace.rendererToMain.batching` is now the owner.\n */\nexport const RENDERER_TRACE_BATCHING_DEFAULTS: RendererTraceBatchingConfig = Object.freeze({\n maxQueuedEvents: 256,\n maxBatchEvents: 32,\n acknowledgementTimeoutMs: 1_000,\n retryLimit: 3,\n retryBaseDelayMs: 25,\n});\n\n/** Resolves the renderer trace batching policy from a parsed config. */\nexport function resolveRendererTraceBatching(\n config: Pick<WoodConfig, 'observability'>,\n): RendererTraceBatchingConfig {\n return {\n ...RENDERER_TRACE_BATCHING_DEFAULTS,\n ...config.observability?.trace?.rendererToMain?.batching,\n };\n}\n\nfunction parseObservability(raw: Record<string, unknown>): WoodConfig['observability'] {\n const trace = raw.trace;\n if (trace === undefined) {\n return {};\n }\n if (typeof trace !== 'object' || trace === null) {\n throw new Error('Config validation error: \"observability.trace\" must be an object');\n }\n const rendererToMain = (trace as Record<string, unknown>).rendererToMain;\n if (rendererToMain === undefined) {\n return { trace: {} };\n }\n if (typeof rendererToMain !== 'object' || rendererToMain === null) {\n throw new Error('Config validation error: \"observability.trace.rendererToMain\" must be an object');\n }\n const batching = (rendererToMain as Record<string, unknown>).batching;\n if (batching === undefined) {\n return { trace: { rendererToMain: {} } };\n }\n if (typeof batching !== 'object' || batching === null) {\n throw new Error('Config validation error: \"observability.trace.rendererToMain.batching\" must be an object');\n }\n\n const resolved: RendererTraceBatchingConfig = {\n ...RENDERER_TRACE_BATCHING_DEFAULTS,\n ...(batching as Partial<RendererTraceBatchingConfig>),\n };\n\n const positiveIntFields = ['maxQueuedEvents', 'maxBatchEvents', 'acknowledgementTimeoutMs'] as const;\n for (const field of positiveIntFields) {\n const value = resolved[field];\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(\n `Config validation error: \"observability.trace.rendererToMain.batching.${field}\" must be a positive integer`,\n );\n }\n }\n if (!Number.isSafeInteger(resolved.retryLimit) || resolved.retryLimit < 0) {\n throw new Error(\n 'Config validation error: \"observability.trace.rendererToMain.batching.retryLimit\" must be a non-negative integer',\n );\n }\n if (!Number.isFinite(resolved.retryBaseDelayMs) || resolved.retryBaseDelayMs < 0) {\n throw new Error(\n 'Config validation error: \"observability.trace.rendererToMain.batching.retryBaseDelayMs\" must be a non-negative number',\n );\n }\n if (resolved.maxBatchEvents > resolved.maxQueuedEvents) {\n throw new Error(\n 'Config validation error: \"observability.trace.rendererToMain.batching.maxBatchEvents\" cannot exceed maxQueuedEvents',\n );\n }\n\n return { trace: { rendererToMain: { batching: resolved } } };\n}\n"],"mappings":"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","names":[]}
|
package/dist/config/index.cjs
CHANGED
|
@@ -18,12 +18,16 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var config_exports = {};
|
|
20
20
|
__export(config_exports, {
|
|
21
|
-
|
|
21
|
+
RENDERER_TRACE_BATCHING_DEFAULTS: () => import_config_parser.RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
22
|
+
parseConfig: () => import_config_parser.parseConfig,
|
|
23
|
+
resolveRendererTraceBatching: () => import_config_parser.resolveRendererTraceBatching
|
|
22
24
|
});
|
|
23
25
|
module.exports = __toCommonJS(config_exports);
|
|
24
26
|
var import_config_parser = require("./config_parser.cjs");
|
|
25
27
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
28
|
0 && (module.exports = {
|
|
27
|
-
|
|
29
|
+
RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
30
|
+
parseConfig,
|
|
31
|
+
resolveRendererTraceBatching
|
|
28
32
|
});
|
|
29
33
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -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.cjs';\nexport type {\n ObservabilityConfig,\n RendererTraceBatchingConfig,\n} from '../types/config.cjs';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAIO;","names":[]}
|
package/dist/config/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { parseConfig } from './config_parser.cjs';
|
|
2
|
-
|
|
1
|
+
export { RENDERER_TRACE_BATCHING_DEFAULTS, parseConfig, resolveRendererTraceBatching } from './config_parser.cjs';
|
|
2
|
+
export { ObservabilityConfig, RendererTraceBatchingConfig } from '../types/config.cjs';
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { parseConfig } from './config_parser.js';
|
|
2
|
-
|
|
1
|
+
export { RENDERER_TRACE_BATCHING_DEFAULTS, parseConfig, resolveRendererTraceBatching } from './config_parser.js';
|
|
2
|
+
export { ObservabilityConfig, RendererTraceBatchingConfig } from '../types/config.js';
|
package/dist/config/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
parseConfig,
|
|
3
|
+
resolveRendererTraceBatching,
|
|
4
|
+
RENDERER_TRACE_BATCHING_DEFAULTS
|
|
5
|
+
} from "./config_parser.js";
|
|
2
6
|
export {
|
|
3
|
-
|
|
7
|
+
RENDERER_TRACE_BATCHING_DEFAULTS,
|
|
8
|
+
parseConfig,
|
|
9
|
+
resolveRendererTraceBatching
|
|
4
10
|
};
|
|
5
11
|
//# sourceMappingURL=index.js.map
|
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":"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","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
|