@noego/wood 0.0.1
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 +107 -0
- package/bin/axe.js +202 -0
- package/bin/stick.js +96 -0
- package/bin/wood.js +572 -0
- package/dist/bridge/backend_bridge.cjs +186 -0
- package/dist/bridge/backend_bridge.cjs.map +1 -0
- package/dist/bridge/backend_bridge.d.cts +32 -0
- package/dist/bridge/backend_bridge.d.ts +32 -0
- package/dist/bridge/backend_bridge.js +152 -0
- package/dist/bridge/backend_bridge.js.map +1 -0
- package/dist/bridge/backend_entry.cjs +64 -0
- package/dist/bridge/backend_entry.cjs.map +1 -0
- package/dist/bridge/backend_entry.d.cts +14 -0
- package/dist/bridge/backend_entry.d.ts +14 -0
- package/dist/bridge/backend_entry.js +39 -0
- package/dist/bridge/backend_entry.js.map +1 -0
- package/dist/bridge/index.cjs +34 -0
- package/dist/bridge/index.cjs.map +1 -0
- package/dist/bridge/index.d.cts +2 -0
- package/dist/bridge/index.d.ts +2 -0
- package/dist/bridge/index.js +8 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/client/controller_contract.cjs +17 -0
- package/dist/client/controller_contract.cjs.map +1 -0
- package/dist/client/controller_contract.d.cts +15 -0
- package/dist/client/controller_contract.d.ts +15 -0
- package/dist/client/controller_contract.js +1 -0
- package/dist/client/controller_contract.js.map +1 -0
- package/dist/client/global_polyfill.cjs +6 -0
- package/dist/client/global_polyfill.cjs.map +1 -0
- package/dist/client/global_polyfill.d.cts +2 -0
- package/dist/client/global_polyfill.d.ts +2 -0
- package/dist/client/global_polyfill.js +5 -0
- package/dist/client/global_polyfill.js.map +1 -0
- package/dist/client/index.cjs +451 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +75 -0
- package/dist/client/index.d.ts +75 -0
- package/dist/client/index.js +414 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/wood_controller.svelte.cjs +110 -0
- package/dist/client/wood_controller.svelte.cjs.map +1 -0
- package/dist/client/wood_controller.svelte.d.cts +30 -0
- package/dist/client/wood_controller.svelte.d.ts +30 -0
- package/dist/client/wood_controller.svelte.js +86 -0
- package/dist/client/wood_controller.svelte.js.map +1 -0
- package/dist/codegen/controller_registration_generator.cjs +138 -0
- package/dist/codegen/controller_registration_generator.cjs.map +1 -0
- package/dist/codegen/controller_registration_generator.d.cts +18 -0
- package/dist/codegen/controller_registration_generator.d.ts +18 -0
- package/dist/codegen/controller_registration_generator.js +104 -0
- package/dist/codegen/controller_registration_generator.js.map +1 -0
- package/dist/codegen/index.cjs +50 -0
- package/dist/codegen/index.cjs.map +1 -0
- package/dist/codegen/index.d.cts +10 -0
- package/dist/codegen/index.d.ts +10 -0
- package/dist/codegen/index.js +19 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/preload_generator.cjs +151 -0
- package/dist/codegen/preload_generator.cjs.map +1 -0
- package/dist/codegen/preload_generator.d.cts +8 -0
- package/dist/codegen/preload_generator.d.ts +8 -0
- package/dist/codegen/preload_generator.js +127 -0
- package/dist/codegen/preload_generator.js.map +1 -0
- package/dist/codegen/renderer_app_generator.cjs +397 -0
- package/dist/codegen/renderer_app_generator.cjs.map +1 -0
- package/dist/codegen/renderer_app_generator.d.cts +13 -0
- package/dist/codegen/renderer_app_generator.d.ts +13 -0
- package/dist/codegen/renderer_app_generator.js +363 -0
- package/dist/codegen/renderer_app_generator.js.map +1 -0
- package/dist/codegen/renderer_controller_registration_generator.cjs +122 -0
- package/dist/codegen/renderer_controller_registration_generator.cjs.map +1 -0
- package/dist/codegen/renderer_controller_registration_generator.d.cts +9 -0
- package/dist/codegen/renderer_controller_registration_generator.d.ts +9 -0
- package/dist/codegen/renderer_controller_registration_generator.js +88 -0
- package/dist/codegen/renderer_controller_registration_generator.js.map +1 -0
- package/dist/codegen/renderer_view_manifest_generator.cjs +126 -0
- package/dist/codegen/renderer_view_manifest_generator.cjs.map +1 -0
- package/dist/codegen/renderer_view_manifest_generator.d.cts +11 -0
- package/dist/codegen/renderer_view_manifest_generator.d.ts +11 -0
- package/dist/codegen/renderer_view_manifest_generator.js +92 -0
- package/dist/codegen/renderer_view_manifest_generator.js.map +1 -0
- package/dist/codegen/runtime_generator.cjs +156 -0
- package/dist/codegen/runtime_generator.cjs.map +1 -0
- package/dist/codegen/runtime_generator.d.cts +14 -0
- package/dist/codegen/runtime_generator.d.ts +14 -0
- package/dist/codegen/runtime_generator.js +122 -0
- package/dist/codegen/runtime_generator.js.map +1 -0
- package/dist/codegen/test_mock_generator.cjs +98 -0
- package/dist/codegen/test_mock_generator.cjs.map +1 -0
- package/dist/codegen/test_mock_generator.d.cts +5 -0
- package/dist/codegen/test_mock_generator.d.ts +5 -0
- package/dist/codegen/test_mock_generator.js +74 -0
- package/dist/codegen/test_mock_generator.js.map +1 -0
- package/dist/codegen/type_generator.cjs +203 -0
- package/dist/codegen/type_generator.cjs.map +1 -0
- package/dist/codegen/type_generator.d.cts +5 -0
- package/dist/codegen/type_generator.d.ts +5 -0
- package/dist/codegen/type_generator.js +179 -0
- package/dist/codegen/type_generator.js.map +1 -0
- package/dist/components/contextMenu.cjs +163 -0
- package/dist/components/contextMenu.cjs.map +1 -0
- package/dist/components/contextMenu.d.cts +43 -0
- package/dist/components/contextMenu.d.ts +43 -0
- package/dist/components/contextMenu.js +138 -0
- package/dist/components/contextMenu.js.map +1 -0
- package/dist/config/config_parser.cjs +176 -0
- package/dist/config/config_parser.cjs.map +1 -0
- package/dist/config/config_parser.d.cts +9 -0
- package/dist/config/config_parser.d.ts +9 -0
- package/dist/config/config_parser.js +142 -0
- package/dist/config/config_parser.js.map +1 -0
- package/dist/config/index.cjs +29 -0
- package/dist/config/index.cjs.map +1 -0
- package/dist/config/index.d.cts +2 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controller/__fixtures__/controllers/chat.cjs +32 -0
- package/dist/controller/__fixtures__/controllers/chat.cjs.map +1 -0
- package/dist/controller/__fixtures__/controllers/chat.d.cts +11 -0
- package/dist/controller/__fixtures__/controllers/chat.d.ts +11 -0
- package/dist/controller/__fixtures__/controllers/chat.js +12 -0
- package/dist/controller/__fixtures__/controllers/chat.js.map +1 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.cjs +29 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +1 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +3 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +3 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.js +5 -0
- package/dist/controller/__fixtures__/controllers/not_a_class.js.map +1 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs +32 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +1 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +12 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +12 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.js +12 -0
- package/dist/controller/__fixtures__/controllers/settings.controller.js.map +1 -0
- package/dist/controller/__fixtures__/controllers/test.cjs +29 -0
- package/dist/controller/__fixtures__/controllers/test.cjs.map +1 -0
- package/dist/controller/__fixtures__/controllers/test.d.cts +7 -0
- package/dist/controller/__fixtures__/controllers/test.d.ts +7 -0
- package/dist/controller/__fixtures__/controllers/test.js +9 -0
- package/dist/controller/__fixtures__/controllers/test.js.map +1 -0
- package/dist/controller/controller_resolver.cjs +180 -0
- package/dist/controller/controller_resolver.cjs.map +1 -0
- package/dist/controller/controller_resolver.d.cts +51 -0
- package/dist/controller/controller_resolver.d.ts +51 -0
- package/dist/controller/controller_resolver.js +145 -0
- package/dist/controller/controller_resolver.js.map +1 -0
- package/dist/controller/index.cjs +31 -0
- package/dist/controller/index.cjs.map +1 -0
- package/dist/controller/index.d.cts +2 -0
- package/dist/controller/index.d.ts +2 -0
- package/dist/controller/index.js +6 -0
- package/dist/controller/index.js.map +1 -0
- package/dist/dev/backend_watcher.cjs +108 -0
- package/dist/dev/backend_watcher.cjs.map +1 -0
- package/dist/dev/backend_watcher.d.cts +22 -0
- package/dist/dev/backend_watcher.d.ts +22 -0
- package/dist/dev/backend_watcher.js +84 -0
- package/dist/dev/backend_watcher.js.map +1 -0
- package/dist/dev/dev_metadata.cjs +94 -0
- package/dist/dev/dev_metadata.cjs.map +1 -0
- package/dist/dev/dev_metadata.d.cts +20 -0
- package/dist/dev/dev_metadata.d.ts +20 -0
- package/dist/dev/dev_metadata.js +52 -0
- package/dist/dev/dev_metadata.js.map +1 -0
- package/dist/dev/esbuild_backend.cjs +124 -0
- package/dist/dev/esbuild_backend.cjs.map +1 -0
- package/dist/dev/esbuild_backend.d.cts +30 -0
- package/dist/dev/esbuild_backend.d.ts +30 -0
- package/dist/dev/esbuild_backend.js +90 -0
- package/dist/dev/esbuild_backend.js.map +1 -0
- package/dist/dev/index.cjs +57 -0
- package/dist/dev/index.cjs.map +1 -0
- package/dist/dev/index.d.cts +8 -0
- package/dist/dev/index.d.ts +8 -0
- package/dist/dev/index.js +31 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/wood_dev_server.cjs +220 -0
- package/dist/dev/wood_dev_server.cjs.map +1 -0
- package/dist/dev/wood_dev_server.d.cts +39 -0
- package/dist/dev/wood_dev_server.d.ts +39 -0
- package/dist/dev/wood_dev_server.js +186 -0
- package/dist/dev/wood_dev_server.js.map +1 -0
- package/dist/dev/yaml_watcher.cjs +142 -0
- package/dist/dev/yaml_watcher.cjs.map +1 -0
- package/dist/dev/yaml_watcher.d.cts +22 -0
- package/dist/dev/yaml_watcher.d.ts +22 -0
- package/dist/dev/yaml_watcher.js +108 -0
- package/dist/dev/yaml_watcher.js.map +1 -0
- package/dist/electron/index.cjs +176 -0
- package/dist/electron/index.cjs.map +1 -0
- package/dist/electron/index.d.cts +29 -0
- package/dist/electron/index.d.ts +29 -0
- package/dist/electron/index.js +140 -0
- package/dist/electron/index.js.map +1 -0
- package/dist/index.cjs +178 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +41 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/index.cjs +80 -0
- package/dist/ipc/index.cjs.map +1 -0
- package/dist/ipc/index.d.cts +12 -0
- package/dist/ipc/index.d.ts +12 -0
- package/dist/ipc/index.js +57 -0
- package/dist/ipc/index.js.map +1 -0
- package/dist/ipc/shared.cjs +50 -0
- package/dist/ipc/shared.cjs.map +1 -0
- package/dist/ipc/shared.d.cts +10 -0
- package/dist/ipc/shared.d.ts +10 -0
- package/dist/ipc/shared.js +23 -0
- package/dist/ipc/shared.js.map +1 -0
- package/dist/loader/__fixtures__/layouts/app.load.cjs +27 -0
- package/dist/loader/__fixtures__/layouts/app.load.cjs.map +1 -0
- package/dist/loader/__fixtures__/layouts/app.load.d.cts +5 -0
- package/dist/loader/__fixtures__/layouts/app.load.d.ts +5 -0
- package/dist/loader/__fixtures__/layouts/app.load.js +7 -0
- package/dist/loader/__fixtures__/layouts/app.load.js.map +1 -0
- package/dist/loader/__fixtures__/views/test/page.load.cjs +27 -0
- package/dist/loader/__fixtures__/views/test/page.load.cjs.map +1 -0
- package/dist/loader/__fixtures__/views/test/page.load.d.cts +6 -0
- package/dist/loader/__fixtures__/views/test/page.load.d.ts +6 -0
- package/dist/loader/__fixtures__/views/test/page.load.js +7 -0
- package/dist/loader/__fixtures__/views/test/page.load.js.map +1 -0
- package/dist/loader/index.cjs +29 -0
- package/dist/loader/index.cjs.map +1 -0
- package/dist/loader/index.d.cts +3 -0
- package/dist/loader/index.d.ts +3 -0
- package/dist/loader/index.js +5 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/loader_runner.cjs +109 -0
- package/dist/loader/loader_runner.cjs.map +1 -0
- package/dist/loader/loader_runner.d.cts +27 -0
- package/dist/loader/loader_runner.d.ts +27 -0
- package/dist/loader/loader_runner.js +75 -0
- package/dist/loader/loader_runner.js.map +1 -0
- package/dist/main/index.cjs +500 -0
- package/dist/main/index.cjs.map +1 -0
- package/dist/main/index.d.cts +98 -0
- package/dist/main/index.d.ts +98 -0
- package/dist/main/index.js +475 -0
- package/dist/main/index.js.map +1 -0
- package/dist/middleware/__fixtures__/middleware/auth.cjs +44 -0
- package/dist/middleware/__fixtures__/middleware/auth.cjs.map +1 -0
- package/dist/middleware/__fixtures__/middleware/auth.d.cts +6 -0
- package/dist/middleware/__fixtures__/middleware/auth.d.ts +6 -0
- package/dist/middleware/__fixtures__/middleware/auth.js +19 -0
- package/dist/middleware/__fixtures__/middleware/auth.js.map +1 -0
- package/dist/middleware/__fixtures__/middleware/sequence.cjs +47 -0
- package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +1 -0
- package/dist/middleware/__fixtures__/middleware/sequence.d.cts +7 -0
- package/dist/middleware/__fixtures__/middleware/sequence.d.ts +7 -0
- package/dist/middleware/__fixtures__/middleware/sequence.js +21 -0
- package/dist/middleware/__fixtures__/middleware/sequence.js.map +1 -0
- package/dist/middleware/index.cjs +34 -0
- package/dist/middleware/index.cjs.map +1 -0
- package/dist/middleware/index.d.cts +3 -0
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/index.js +8 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/middleware_pipeline.cjs +55 -0
- package/dist/middleware/middleware_pipeline.cjs.map +1 -0
- package/dist/middleware/middleware_pipeline.d.cts +13 -0
- package/dist/middleware/middleware_pipeline.d.ts +13 -0
- package/dist/middleware/middleware_pipeline.js +30 -0
- package/dist/middleware/middleware_pipeline.js.map +1 -0
- package/dist/middleware/middleware_resolver.cjs +91 -0
- package/dist/middleware/middleware_resolver.cjs.map +1 -0
- package/dist/middleware/middleware_resolver.d.cts +19 -0
- package/dist/middleware/middleware_resolver.d.ts +19 -0
- package/dist/middleware/middleware_resolver.js +57 -0
- package/dist/middleware/middleware_resolver.js.map +1 -0
- package/dist/navigation/index.cjs +205 -0
- package/dist/navigation/index.cjs.map +1 -0
- package/dist/navigation/index.d.cts +34 -0
- package/dist/navigation/index.d.ts +34 -0
- package/dist/navigation/index.js +176 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/parser/index.cjs +36 -0
- package/dist/parser/index.cjs.map +1 -0
- package/dist/parser/index.d.cts +4 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.js +9 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/operations_parser.cjs +94 -0
- package/dist/parser/operations_parser.cjs.map +1 -0
- package/dist/parser/operations_parser.d.cts +7 -0
- package/dist/parser/operations_parser.d.ts +7 -0
- package/dist/parser/operations_parser.js +59 -0
- package/dist/parser/operations_parser.js.map +1 -0
- package/dist/parser/views_parser.cjs +153 -0
- package/dist/parser/views_parser.cjs.map +1 -0
- package/dist/parser/views_parser.d.cts +11 -0
- package/dist/parser/views_parser.d.ts +11 -0
- package/dist/parser/views_parser.js +118 -0
- package/dist/parser/views_parser.js.map +1 -0
- package/dist/router/index.cjs +31 -0
- package/dist/router/index.cjs.map +1 -0
- package/dist/router/index.d.cts +2 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.js +6 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/wood_router.cjs +246 -0
- package/dist/router/wood_router.cjs.map +1 -0
- package/dist/router/wood_router.d.cts +70 -0
- package/dist/router/wood_router.d.ts +70 -0
- package/dist/router/wood_router.js +221 -0
- package/dist/router/wood_router.js.map +1 -0
- package/dist/runtime/application_root.cjs +98 -0
- package/dist/runtime/application_root.cjs.map +1 -0
- package/dist/runtime/application_root.d.cts +5 -0
- package/dist/runtime/application_root.d.ts +5 -0
- package/dist/runtime/application_root.js +61 -0
- package/dist/runtime/application_root.js.map +1 -0
- package/dist/runtime/get_container.cjs +96 -0
- package/dist/runtime/get_container.cjs.map +1 -0
- package/dist/runtime/get_container.d.cts +16 -0
- package/dist/runtime/get_container.d.ts +16 -0
- package/dist/runtime/get_container.js +60 -0
- package/dist/runtime/get_container.js.map +1 -0
- package/dist/runtime/index.cjs +49 -0
- package/dist/runtime/index.cjs.map +1 -0
- package/dist/runtime/index.d.cts +8 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +24 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/renderer_log_dispatcher.cjs +79 -0
- package/dist/runtime/renderer_log_dispatcher.cjs.map +1 -0
- package/dist/runtime/renderer_log_dispatcher.d.cts +27 -0
- package/dist/runtime/renderer_log_dispatcher.d.ts +27 -0
- package/dist/runtime/renderer_log_dispatcher.js +54 -0
- package/dist/runtime/renderer_log_dispatcher.js.map +1 -0
- package/dist/runtime/runtime.cjs +158 -0
- package/dist/runtime/runtime.cjs.map +1 -0
- package/dist/runtime/runtime.d.cts +35 -0
- package/dist/runtime/runtime.d.ts +35 -0
- package/dist/runtime/runtime.js +136 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/stick/allow_cli.cjs +39 -0
- package/dist/stick/allow_cli.cjs.map +1 -0
- package/dist/stick/allow_cli.d.cts +6 -0
- package/dist/stick/allow_cli.d.ts +6 -0
- package/dist/stick/allow_cli.js +15 -0
- package/dist/stick/allow_cli.js.map +1 -0
- package/dist/stick/index.cjs +276 -0
- package/dist/stick/index.cjs.map +1 -0
- package/dist/stick/index.d.cts +111 -0
- package/dist/stick/index.d.ts +111 -0
- package/dist/stick/index.js +237 -0
- package/dist/stick/index.js.map +1 -0
- package/dist/stick/static_renderer.cjs +144 -0
- package/dist/stick/static_renderer.cjs.map +1 -0
- package/dist/stick/static_renderer.d.cts +51 -0
- package/dist/stick/static_renderer.d.ts +51 -0
- package/dist/stick/static_renderer.js +119 -0
- package/dist/stick/static_renderer.js.map +1 -0
- package/dist/stick/template_resolver.cjs +156 -0
- package/dist/stick/template_resolver.cjs.map +1 -0
- package/dist/stick/template_resolver.d.cts +7 -0
- package/dist/stick/template_resolver.d.ts +7 -0
- package/dist/stick/template_resolver.js +122 -0
- package/dist/stick/template_resolver.js.map +1 -0
- package/dist/testing/create_controller_harness.cjs +175 -0
- package/dist/testing/create_controller_harness.cjs.map +1 -0
- package/dist/testing/create_controller_harness.d.cts +37 -0
- package/dist/testing/create_controller_harness.d.ts +37 -0
- package/dist/testing/create_controller_harness.js +162 -0
- package/dist/testing/create_controller_harness.js.map +1 -0
- package/dist/testing/create_router_bridge.cjs +103 -0
- package/dist/testing/create_router_bridge.cjs.map +1 -0
- package/dist/testing/create_router_bridge.d.cts +71 -0
- package/dist/testing/create_router_bridge.d.ts +71 -0
- package/dist/testing/create_router_bridge.js +78 -0
- package/dist/testing/create_router_bridge.js.map +1 -0
- package/dist/testing/create_test_container.cjs +72 -0
- package/dist/testing/create_test_container.cjs.map +1 -0
- package/dist/testing/create_test_container.d.cts +14 -0
- package/dist/testing/create_test_container.d.ts +14 -0
- package/dist/testing/create_test_container.js +48 -0
- package/dist/testing/create_test_container.js.map +1 -0
- package/dist/testing/create_test_router.cjs +57 -0
- package/dist/testing/create_test_router.cjs.map +1 -0
- package/dist/testing/create_test_router.d.cts +19 -0
- package/dist/testing/create_test_router.d.ts +19 -0
- package/dist/testing/create_test_router.js +33 -0
- package/dist/testing/create_test_router.js.map +1 -0
- package/dist/testing/index.cjs +48 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +12 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock_electron.cjs +100 -0
- package/dist/testing/mock_electron.cjs.map +1 -0
- package/dist/testing/mock_electron.d.cts +12 -0
- package/dist/testing/mock_electron.d.ts +12 -0
- package/dist/testing/mock_electron.js +75 -0
- package/dist/testing/mock_electron.js.map +1 -0
- package/dist/tracing/index.cjs +56 -0
- package/dist/tracing/index.cjs.map +1 -0
- package/dist/tracing/index.d.cts +4 -0
- package/dist/tracing/index.d.ts +4 -0
- package/dist/tracing/index.js +35 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/trace_hub.cjs +213 -0
- package/dist/tracing/trace_hub.cjs.map +1 -0
- package/dist/tracing/trace_hub.d.cts +47 -0
- package/dist/tracing/trace_hub.d.ts +47 -0
- package/dist/tracing/trace_hub.js +172 -0
- package/dist/tracing/trace_hub.js.map +1 -0
- package/dist/tracing/trace_provider.cjs +200 -0
- package/dist/tracing/trace_provider.cjs.map +1 -0
- package/dist/tracing/trace_provider.d.cts +69 -0
- package/dist/tracing/trace_provider.d.ts +69 -0
- package/dist/tracing/trace_provider.js +179 -0
- package/dist/tracing/trace_provider.js.map +1 -0
- package/dist/types/bridge.cjs +51 -0
- package/dist/types/bridge.cjs.map +1 -0
- package/dist/types/bridge.d.cts +56 -0
- package/dist/types/bridge.d.ts +56 -0
- package/dist/types/bridge.js +25 -0
- package/dist/types/bridge.js.map +1 -0
- package/dist/types/config.cjs +17 -0
- package/dist/types/config.cjs.map +1 -0
- package/dist/types/config.d.cts +74 -0
- package/dist/types/config.d.ts +74 -0
- package/dist/types/config.js +1 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/context.cjs +17 -0
- package/dist/types/context.cjs.map +1 -0
- package/dist/types/context.d.cts +61 -0
- package/dist/types/context.d.ts +61 -0
- package/dist/types/context.js +1 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/context_menu.cjs +17 -0
- package/dist/types/context_menu.cjs.map +1 -0
- package/dist/types/context_menu.d.cts +30 -0
- package/dist/types/context_menu.d.ts +30 -0
- package/dist/types/context_menu.js +1 -0
- package/dist/types/context_menu.js.map +1 -0
- package/dist/types/index.cjs +33 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +6 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/operations.cjs +17 -0
- package/dist/types/operations.cjs.map +1 -0
- package/dist/types/operations.d.cts +39 -0
- package/dist/types/operations.d.ts +39 -0
- package/dist/types/operations.js +1 -0
- package/dist/types/operations.js.map +1 -0
- package/dist/types/views.cjs +17 -0
- package/dist/types/views.cjs.map +1 -0
- package/dist/types/views.d.cts +44 -0
- package/dist/types/views.d.ts +44 -0
- package/dist/types/views.js +1 -0
- package/dist/types/views.js.map +1 -0
- package/dist/validation/index.cjs +29 -0
- package/dist/validation/index.cjs.map +1 -0
- package/dist/validation/index.d.cts +1 -0
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +5 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/schema_validator.cjs +86 -0
- package/dist/validation/schema_validator.cjs.map +1 -0
- package/dist/validation/schema_validator.d.cts +24 -0
- package/dist/validation/schema_validator.d.ts +24 -0
- package/dist/validation/schema_validator.js +52 -0
- package/dist/validation/schema_validator.js.map +1 -0
- package/dist/window/index.cjs +32 -0
- package/dist/window/index.cjs.map +1 -0
- package/dist/window/index.d.cts +4 -0
- package/dist/window/index.d.ts +4 -0
- package/dist/window/index.js +7 -0
- package/dist/window/index.js.map +1 -0
- package/dist/window/window_manager.cjs +354 -0
- package/dist/window/window_manager.cjs.map +1 -0
- package/dist/window/window_manager.d.cts +172 -0
- package/dist/window/window_manager.d.ts +172 -0
- package/dist/window/window_manager.js +330 -0
- package/dist/window/window_manager.js.map +1 -0
- package/dist/window/window_state_store.cjs +129 -0
- package/dist/window/window_state_store.cjs.map +1 -0
- package/dist/window/window_state_store.d.cts +39 -0
- package/dist/window/window_state_store.d.ts +39 -0
- package/dist/window/window_state_store.js +105 -0
- package/dist/window/window_state_store.js.map +1 -0
- package/loaders/loader.mjs +46 -0
- package/package.json +119 -0
- package/src/components/ContextMenuProvider.svelte +145 -0
- package/src/components/NavigationShell.svelte +204 -0
- package/src/components/WoodRecursiveRender.svelte +91 -0
- package/src/components/contextMenu.ts +228 -0
- package/src/components/index.d.ts +14 -0
- package/src/components/index.js +2 -0
- package/src/stick/WoodRecursiveRender.svelte +74 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var wood_router_exports = {};
|
|
20
|
+
__export(wood_router_exports, {
|
|
21
|
+
RESERVED_CHANNELS: () => RESERVED_CHANNELS,
|
|
22
|
+
WoodRouter: () => WoodRouter
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(wood_router_exports);
|
|
25
|
+
var import_schema_validator = require("../validation/schema_validator.cjs");
|
|
26
|
+
var import_middleware_resolver = require("../middleware/middleware_resolver.cjs");
|
|
27
|
+
var import_middleware_pipeline = require("../middleware/middleware_pipeline.cjs");
|
|
28
|
+
var import_controller_resolver = require("../controller/controller_resolver.cjs");
|
|
29
|
+
var import_logger = require("@noego/logger");
|
|
30
|
+
var import_tracing = require("../tracing/index.js");
|
|
31
|
+
const logger = (0, import_logger.getLogger)("wood:router");
|
|
32
|
+
function extractTraceConversationId(value) {
|
|
33
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
const record = value;
|
|
37
|
+
if (typeof record.conversationId === "number" || typeof record.conversationId === "string") {
|
|
38
|
+
return record.conversationId;
|
|
39
|
+
}
|
|
40
|
+
if (typeof record.threadId === "number" || typeof record.threadId === "string") {
|
|
41
|
+
return record.threadId;
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
const RESERVED_CHANNELS = ["__load", "__navigate", "__window", "__debug", "__contextMenu"];
|
|
46
|
+
class WoodRouter {
|
|
47
|
+
// IoC Container
|
|
48
|
+
constructor(options) {
|
|
49
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
50
|
+
this.reservedHandlers = /* @__PURE__ */ new Map();
|
|
51
|
+
this.container = options.container;
|
|
52
|
+
this.validator = new import_schema_validator.SchemaValidator();
|
|
53
|
+
this.middlewareResolver = new import_middleware_resolver.MiddlewareResolver(options.middlewareDir);
|
|
54
|
+
this.controllerResolver = new import_controller_resolver.ControllerResolver(options.controllersDir, {
|
|
55
|
+
mode: options.mode
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Load operations from a parsed operations map.
|
|
60
|
+
*/
|
|
61
|
+
loadOperations(operations) {
|
|
62
|
+
for (const [channel, opDef] of operations) {
|
|
63
|
+
this.operations.set(channel, opDef);
|
|
64
|
+
}
|
|
65
|
+
logger.debug(`Loaded ${operations.size} operations`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Register a handler for a reserved channel (__load, __navigate, __window).
|
|
69
|
+
* These channels are internal to Wood and serve as extension points for
|
|
70
|
+
* the loader runner, navigation system, and window manager.
|
|
71
|
+
*/
|
|
72
|
+
registerReservedHandler(channel, handler) {
|
|
73
|
+
this.reservedHandlers.set(channel, handler);
|
|
74
|
+
logger.debug(`Registered reserved handler for "${channel}"`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Register IPC handlers for all operations and reserved channels.
|
|
78
|
+
* In production: registers with ipcMain.handle
|
|
79
|
+
* In testing/bridge mode: handlers are callable via dispatch()
|
|
80
|
+
*/
|
|
81
|
+
registerIpcHandlers(ipcMain) {
|
|
82
|
+
for (const channel of this.operations.keys()) {
|
|
83
|
+
ipcMain.handle(channel, async (_event, data) => {
|
|
84
|
+
return this.dispatch(channel, data, _event);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
for (const channel of RESERVED_CHANNELS) {
|
|
88
|
+
ipcMain.handle(channel, async (_event, data) => {
|
|
89
|
+
const handler = this.reservedHandlers.get(channel);
|
|
90
|
+
if (!handler) {
|
|
91
|
+
throw new Error(`No handler registered for reserved channel "${channel}"`);
|
|
92
|
+
}
|
|
93
|
+
return handler(data, _event);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
logger.debug(
|
|
97
|
+
`Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The request lifecycle -- mirrors Dinner's pipeline.
|
|
102
|
+
*
|
|
103
|
+
* channel -> build context -> middleware -> validate -> resolve controller
|
|
104
|
+
* -> create instance -> build args -> call action -> return result
|
|
105
|
+
*/
|
|
106
|
+
async dispatch(channel, data, event) {
|
|
107
|
+
const opDef = this.operations.get(channel);
|
|
108
|
+
if (!opDef) {
|
|
109
|
+
throw new Error(`Unknown operation: "${channel}"`);
|
|
110
|
+
}
|
|
111
|
+
const conversationId = extractTraceConversationId(data);
|
|
112
|
+
(0, import_tracing.publishMainTrace)("debug", {
|
|
113
|
+
source: "wood.router",
|
|
114
|
+
type: "dispatch.start",
|
|
115
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
116
|
+
payload: {
|
|
117
|
+
channel,
|
|
118
|
+
controller: opDef.controller,
|
|
119
|
+
action: opDef.action
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const ipcContext = {
|
|
123
|
+
body: data ?? {},
|
|
124
|
+
params: data ?? {},
|
|
125
|
+
query: {},
|
|
126
|
+
context: {},
|
|
127
|
+
sender: event?.sender,
|
|
128
|
+
windowId: void 0
|
|
129
|
+
};
|
|
130
|
+
if (opDef.middleware.length > 0) {
|
|
131
|
+
const mwContext = (0, import_middleware_pipeline.buildMiddlewareContext)(ipcContext, channel);
|
|
132
|
+
const middlewareFns = await Promise.all(
|
|
133
|
+
opDef.middleware.map((spec) => this.middlewareResolver.resolve(spec))
|
|
134
|
+
);
|
|
135
|
+
await (0, import_middleware_pipeline.executeMiddleware)(middlewareFns, mwContext);
|
|
136
|
+
}
|
|
137
|
+
if (opDef.inputSchema) {
|
|
138
|
+
const result = this.validator.validate(
|
|
139
|
+
channel,
|
|
140
|
+
opDef.inputSchema,
|
|
141
|
+
ipcContext.body
|
|
142
|
+
);
|
|
143
|
+
if (!result.valid) {
|
|
144
|
+
return {
|
|
145
|
+
error: "VALIDATION_ERROR",
|
|
146
|
+
message: "Request validation failed",
|
|
147
|
+
details: result.errors
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);
|
|
152
|
+
const scopedContainer = this.container.extend();
|
|
153
|
+
const instance = await scopedContainer.instance(ControllerClass);
|
|
154
|
+
const args = (0, import_controller_resolver.buildControllerArgs)(ipcContext, scopedContainer);
|
|
155
|
+
const action = instance[opDef.action];
|
|
156
|
+
if (typeof action !== "function") {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`Controller "${opDef.controller}" has no action "${opDef.action}"`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const result = await action.call(instance, args);
|
|
163
|
+
(0, import_tracing.publishMainTrace)("debug", {
|
|
164
|
+
source: "wood.router",
|
|
165
|
+
type: "dispatch.success",
|
|
166
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
167
|
+
payload: {
|
|
168
|
+
channel,
|
|
169
|
+
controller: opDef.controller,
|
|
170
|
+
action: opDef.action
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return result;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
(0, import_tracing.publishMainTrace)("error", {
|
|
176
|
+
source: "wood.router",
|
|
177
|
+
type: "dispatch.error",
|
|
178
|
+
message: error instanceof Error ? error.message : String(error),
|
|
179
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
180
|
+
payload: {
|
|
181
|
+
channel,
|
|
182
|
+
controller: opDef.controller,
|
|
183
|
+
action: opDef.action
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Pre-register a controller class by name so it is resolved from
|
|
191
|
+
* the in-memory cache instead of the filesystem.
|
|
192
|
+
* This is the public API used by the generated registration file.
|
|
193
|
+
*/
|
|
194
|
+
registerController(name, ControllerClass) {
|
|
195
|
+
this.controllerResolver.register(name, ControllerClass);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Register an import path for a controller. The controller will be lazily
|
|
199
|
+
* imported from this path when first needed, avoiding circular dependencies.
|
|
200
|
+
*/
|
|
201
|
+
registerControllerPath(name, importPath) {
|
|
202
|
+
this.controllerResolver.registerPath(name, importPath);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Validate that every controller referenced in loaded operations is
|
|
206
|
+
* pre-registered in the controller resolver. Call this after
|
|
207
|
+
* loadOperations() + registerControllers() but before registerIpcHandlers().
|
|
208
|
+
*
|
|
209
|
+
* Throws with a clear error listing all missing controllers if any
|
|
210
|
+
* operation references a controller that was not pre-registered.
|
|
211
|
+
*/
|
|
212
|
+
validateControllers() {
|
|
213
|
+
const missing = [];
|
|
214
|
+
for (const [channel, opDef] of this.operations) {
|
|
215
|
+
if (!this.controllerResolver.has(opDef.controller)) {
|
|
216
|
+
missing.push({ channel, controller: opDef.controller });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (missing.length > 0) {
|
|
220
|
+
const details = missing.map((m) => ` - channel "${m.channel}" requires controller "${m.controller}"`).join("\n");
|
|
221
|
+
throw new Error(
|
|
222
|
+
`WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.
|
|
223
|
+
This usually means controllers.generated.ts is missing or out of date.
|
|
224
|
+
Run "npx wood build" or "npx wood dev" to regenerate it.
|
|
225
|
+
|
|
226
|
+
Missing controllers:
|
|
227
|
+
${details}`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
logger.info(`All ${this.operations.size} operations have registered controllers`);
|
|
231
|
+
}
|
|
232
|
+
/** Get all registered operation channels. */
|
|
233
|
+
getChannels() {
|
|
234
|
+
return Array.from(this.operations.keys());
|
|
235
|
+
}
|
|
236
|
+
/** Get a specific operation definition. */
|
|
237
|
+
getOperation(channel) {
|
|
238
|
+
return this.operations.get(channel);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
242
|
+
0 && (module.exports = {
|
|
243
|
+
RESERVED_CHANNELS,
|
|
244
|
+
WoodRouter
|
|
245
|
+
});
|
|
246
|
+
//# sourceMappingURL=wood_router.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.cjs';\nimport { SchemaValidator } from '../validation/schema_validator.cjs';\nimport { MiddlewareResolver } from '../middleware/middleware_resolver.cjs';\nimport { buildMiddlewareContext, executeMiddleware } from '../middleware/middleware_pipeline.cjs';\nimport { ControllerResolver, buildControllerArgs } from '../controller/controller_resolver.cjs';\nimport { getLogger } from '@noego/logger';\nimport { publishMainTrace } from '../tracing/index.js';\n\nconst logger = getLogger('wood:router');\n\nfunction extractTraceConversationId(value: unknown): number | string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n if (typeof record.conversationId === 'number' || typeof record.conversationId === 'string') {\n return record.conversationId;\n }\n if (typeof record.threadId === 'number' || typeof record.threadId === 'string') {\n return record.threadId;\n }\n\n return undefined;\n}\n\n/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */\nexport const RESERVED_CHANNELS = ['__load', '__navigate', '__window', '__debug', '__contextMenu'] as const;\nexport type ReservedChannel = (typeof RESERVED_CHANNELS)[number];\n\n/** Handler signature for reserved channels. */\nexport type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;\n\nexport class WoodRouter {\n private operations = new Map<string, OperationDef>();\n private reservedHandlers = new Map<ReservedChannel, ReservedChannelHandler>();\n private validator: SchemaValidator;\n private middlewareResolver: MiddlewareResolver;\n private controllerResolver: ControllerResolver;\n private container: any; // IoC Container\n\n constructor(options: {\n container: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n }) {\n this.container = options.container;\n this.validator = new SchemaValidator();\n this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);\n this.controllerResolver = new ControllerResolver(options.controllersDir, {\n mode: options.mode,\n });\n }\n\n /**\n * Load operations from a parsed operations map.\n */\n loadOperations(operations: Map<string, OperationDef>): void {\n for (const [channel, opDef] of operations) {\n this.operations.set(channel, opDef);\n }\n logger.debug(`Loaded ${operations.size} operations`);\n }\n\n /**\n * Register a handler for a reserved channel (__load, __navigate, __window).\n * These channels are internal to Wood and serve as extension points for\n * the loader runner, navigation system, and window manager.\n */\n registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void {\n this.reservedHandlers.set(channel, handler);\n logger.debug(`Registered reserved handler for \"${channel}\"`);\n }\n\n /**\n * Register IPC handlers for all operations and reserved channels.\n * In production: registers with ipcMain.handle\n * In testing/bridge mode: handlers are callable via dispatch()\n */\n registerIpcHandlers(ipcMain: any): void {\n for (const channel of this.operations.keys()) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n return this.dispatch(channel, data, _event);\n });\n }\n\n // Register reserved channels\n for (const channel of RESERVED_CHANNELS) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n const handler = this.reservedHandlers.get(channel);\n if (!handler) {\n throw new Error(`No handler registered for reserved channel \"${channel}\"`);\n }\n return handler(data, _event);\n });\n }\n\n logger.debug(\n `Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`\n );\n }\n\n /**\n * The request lifecycle -- mirrors Dinner's pipeline.\n *\n * channel -> build context -> middleware -> validate -> resolve controller\n * -> create instance -> build args -> call action -> return result\n */\n async dispatch(channel: string, data: unknown, event?: any): Promise<unknown> {\n const opDef = this.operations.get(channel);\n if (!opDef) {\n throw new Error(`Unknown operation: \"${channel}\"`);\n }\n\n const conversationId = extractTraceConversationId(data);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.start',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n\n // 1. Build IPC context\n const ipcContext: IpcContext = {\n body: data ?? {},\n params: (data as any) ?? {},\n query: {},\n context: {},\n sender: event?.sender,\n windowId: undefined,\n };\n\n // 2. Execute middleware sequentially\n if (opDef.middleware.length > 0) {\n const mwContext = buildMiddlewareContext(ipcContext, channel);\n const middlewareFns = await Promise.all(\n opDef.middleware.map(spec => this.middlewareResolver.resolve(spec))\n );\n await executeMiddleware(middlewareFns, mwContext);\n }\n\n // 3. Validate input (if schema defined)\n if (opDef.inputSchema) {\n const result = this.validator.validate(\n channel,\n opDef.inputSchema as Record<string, unknown>,\n ipcContext.body\n );\n if (!result.valid) {\n return {\n error: 'VALIDATION_ERROR',\n message: 'Request validation failed',\n details: result.errors,\n };\n }\n }\n\n // 4. Resolve controller class (cached)\n const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);\n\n // 5. Create instance via IoC (per-request scoped container)\n const scopedContainer = this.container.extend();\n const instance = await scopedContainer.instance(ControllerClass);\n\n // 6. Build controller args (fake req/res)\n const args = buildControllerArgs(ipcContext, scopedContainer);\n\n // 7. Call action, return result\n const action = instance[opDef.action];\n if (typeof action !== 'function') {\n throw new Error(\n `Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`\n );\n }\n\n try {\n const result = await action.call(instance, args);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.success',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n return result;\n } catch (error) {\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.error',\n message: error instanceof Error ? error.message : String(error),\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n throw error;\n }\n }\n\n /**\n * Pre-register a controller class by name so it is resolved from\n * the in-memory cache instead of the filesystem.\n * This is the public API used by the generated registration file.\n */\n registerController(name: string, ControllerClass: any): void {\n this.controllerResolver.register(name, ControllerClass);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed, avoiding circular dependencies.\n */\n registerControllerPath(name: string, importPath: string): void {\n this.controllerResolver.registerPath(name, importPath);\n }\n\n /**\n * Validate that every controller referenced in loaded operations is\n * pre-registered in the controller resolver. Call this after\n * loadOperations() + registerControllers() but before registerIpcHandlers().\n *\n * Throws with a clear error listing all missing controllers if any\n * operation references a controller that was not pre-registered.\n */\n validateControllers(): void {\n const missing: Array<{ channel: string; controller: string }> = [];\n\n for (const [channel, opDef] of this.operations) {\n if (!this.controllerResolver.has(opDef.controller)) {\n missing.push({ channel, controller: opDef.controller });\n }\n }\n\n if (missing.length > 0) {\n const details = missing\n .map(m => ` - channel \"${m.channel}\" requires controller \"${m.controller}\"`)\n .join('\\n');\n\n throw new Error(\n `WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.\\n` +\n `This usually means controllers.generated.ts is missing or out of date.\\n` +\n `Run \"npx wood build\" or \"npx wood dev\" to regenerate it.\\n\\n` +\n `Missing controllers:\\n${details}`\n );\n }\n\n logger.info(`All ${this.operations.size} operations have registered controllers`);\n }\n\n /** Get all registered operation channels. */\n getChannels(): string[] {\n return Array.from(this.operations.keys());\n }\n\n /** Get a specific operation definition. */\n getOperation(channel: string): OperationDef | undefined {\n return this.operations.get(channel);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { OperationDef } from '../types/operations.cjs';
|
|
2
|
+
|
|
3
|
+
/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */
|
|
4
|
+
declare const RESERVED_CHANNELS: readonly ["__load", "__navigate", "__window", "__debug", "__contextMenu"];
|
|
5
|
+
type ReservedChannel = (typeof RESERVED_CHANNELS)[number];
|
|
6
|
+
/** Handler signature for reserved channels. */
|
|
7
|
+
type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;
|
|
8
|
+
declare class WoodRouter {
|
|
9
|
+
private operations;
|
|
10
|
+
private reservedHandlers;
|
|
11
|
+
private validator;
|
|
12
|
+
private middlewareResolver;
|
|
13
|
+
private controllerResolver;
|
|
14
|
+
private container;
|
|
15
|
+
constructor(options: {
|
|
16
|
+
container: any;
|
|
17
|
+
controllersDir: string;
|
|
18
|
+
middlewareDir: string;
|
|
19
|
+
mode?: 'bundled' | 'dev';
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Load operations from a parsed operations map.
|
|
23
|
+
*/
|
|
24
|
+
loadOperations(operations: Map<string, OperationDef>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Register a handler for a reserved channel (__load, __navigate, __window).
|
|
27
|
+
* These channels are internal to Wood and serve as extension points for
|
|
28
|
+
* the loader runner, navigation system, and window manager.
|
|
29
|
+
*/
|
|
30
|
+
registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void;
|
|
31
|
+
/**
|
|
32
|
+
* Register IPC handlers for all operations and reserved channels.
|
|
33
|
+
* In production: registers with ipcMain.handle
|
|
34
|
+
* In testing/bridge mode: handlers are callable via dispatch()
|
|
35
|
+
*/
|
|
36
|
+
registerIpcHandlers(ipcMain: any): void;
|
|
37
|
+
/**
|
|
38
|
+
* The request lifecycle -- mirrors Dinner's pipeline.
|
|
39
|
+
*
|
|
40
|
+
* channel -> build context -> middleware -> validate -> resolve controller
|
|
41
|
+
* -> create instance -> build args -> call action -> return result
|
|
42
|
+
*/
|
|
43
|
+
dispatch(channel: string, data: unknown, event?: any): Promise<unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Pre-register a controller class by name so it is resolved from
|
|
46
|
+
* the in-memory cache instead of the filesystem.
|
|
47
|
+
* This is the public API used by the generated registration file.
|
|
48
|
+
*/
|
|
49
|
+
registerController(name: string, ControllerClass: any): void;
|
|
50
|
+
/**
|
|
51
|
+
* Register an import path for a controller. The controller will be lazily
|
|
52
|
+
* imported from this path when first needed, avoiding circular dependencies.
|
|
53
|
+
*/
|
|
54
|
+
registerControllerPath(name: string, importPath: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Validate that every controller referenced in loaded operations is
|
|
57
|
+
* pre-registered in the controller resolver. Call this after
|
|
58
|
+
* loadOperations() + registerControllers() but before registerIpcHandlers().
|
|
59
|
+
*
|
|
60
|
+
* Throws with a clear error listing all missing controllers if any
|
|
61
|
+
* operation references a controller that was not pre-registered.
|
|
62
|
+
*/
|
|
63
|
+
validateControllers(): void;
|
|
64
|
+
/** Get all registered operation channels. */
|
|
65
|
+
getChannels(): string[];
|
|
66
|
+
/** Get a specific operation definition. */
|
|
67
|
+
getOperation(channel: string): OperationDef | undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { RESERVED_CHANNELS, type ReservedChannel, type ReservedChannelHandler, WoodRouter };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { OperationDef } from '../types/operations.js';
|
|
2
|
+
|
|
3
|
+
/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */
|
|
4
|
+
declare const RESERVED_CHANNELS: readonly ["__load", "__navigate", "__window", "__debug", "__contextMenu"];
|
|
5
|
+
type ReservedChannel = (typeof RESERVED_CHANNELS)[number];
|
|
6
|
+
/** Handler signature for reserved channels. */
|
|
7
|
+
type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;
|
|
8
|
+
declare class WoodRouter {
|
|
9
|
+
private operations;
|
|
10
|
+
private reservedHandlers;
|
|
11
|
+
private validator;
|
|
12
|
+
private middlewareResolver;
|
|
13
|
+
private controllerResolver;
|
|
14
|
+
private container;
|
|
15
|
+
constructor(options: {
|
|
16
|
+
container: any;
|
|
17
|
+
controllersDir: string;
|
|
18
|
+
middlewareDir: string;
|
|
19
|
+
mode?: 'bundled' | 'dev';
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Load operations from a parsed operations map.
|
|
23
|
+
*/
|
|
24
|
+
loadOperations(operations: Map<string, OperationDef>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Register a handler for a reserved channel (__load, __navigate, __window).
|
|
27
|
+
* These channels are internal to Wood and serve as extension points for
|
|
28
|
+
* the loader runner, navigation system, and window manager.
|
|
29
|
+
*/
|
|
30
|
+
registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void;
|
|
31
|
+
/**
|
|
32
|
+
* Register IPC handlers for all operations and reserved channels.
|
|
33
|
+
* In production: registers with ipcMain.handle
|
|
34
|
+
* In testing/bridge mode: handlers are callable via dispatch()
|
|
35
|
+
*/
|
|
36
|
+
registerIpcHandlers(ipcMain: any): void;
|
|
37
|
+
/**
|
|
38
|
+
* The request lifecycle -- mirrors Dinner's pipeline.
|
|
39
|
+
*
|
|
40
|
+
* channel -> build context -> middleware -> validate -> resolve controller
|
|
41
|
+
* -> create instance -> build args -> call action -> return result
|
|
42
|
+
*/
|
|
43
|
+
dispatch(channel: string, data: unknown, event?: any): Promise<unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Pre-register a controller class by name so it is resolved from
|
|
46
|
+
* the in-memory cache instead of the filesystem.
|
|
47
|
+
* This is the public API used by the generated registration file.
|
|
48
|
+
*/
|
|
49
|
+
registerController(name: string, ControllerClass: any): void;
|
|
50
|
+
/**
|
|
51
|
+
* Register an import path for a controller. The controller will be lazily
|
|
52
|
+
* imported from this path when first needed, avoiding circular dependencies.
|
|
53
|
+
*/
|
|
54
|
+
registerControllerPath(name: string, importPath: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Validate that every controller referenced in loaded operations is
|
|
57
|
+
* pre-registered in the controller resolver. Call this after
|
|
58
|
+
* loadOperations() + registerControllers() but before registerIpcHandlers().
|
|
59
|
+
*
|
|
60
|
+
* Throws with a clear error listing all missing controllers if any
|
|
61
|
+
* operation references a controller that was not pre-registered.
|
|
62
|
+
*/
|
|
63
|
+
validateControllers(): void;
|
|
64
|
+
/** Get all registered operation channels. */
|
|
65
|
+
getChannels(): string[];
|
|
66
|
+
/** Get a specific operation definition. */
|
|
67
|
+
getOperation(channel: string): OperationDef | undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { RESERVED_CHANNELS, type ReservedChannel, type ReservedChannelHandler, WoodRouter };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { SchemaValidator } from "../validation/schema_validator.js";
|
|
2
|
+
import { MiddlewareResolver } from "../middleware/middleware_resolver.js";
|
|
3
|
+
import { buildMiddlewareContext, executeMiddleware } from "../middleware/middleware_pipeline.js";
|
|
4
|
+
import { ControllerResolver, buildControllerArgs } from "../controller/controller_resolver.js";
|
|
5
|
+
import { getLogger } from "@noego/logger";
|
|
6
|
+
import { publishMainTrace } from "../tracing/index.js";
|
|
7
|
+
const logger = getLogger("wood:router");
|
|
8
|
+
function extractTraceConversationId(value) {
|
|
9
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
const record = value;
|
|
13
|
+
if (typeof record.conversationId === "number" || typeof record.conversationId === "string") {
|
|
14
|
+
return record.conversationId;
|
|
15
|
+
}
|
|
16
|
+
if (typeof record.threadId === "number" || typeof record.threadId === "string") {
|
|
17
|
+
return record.threadId;
|
|
18
|
+
}
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
const RESERVED_CHANNELS = ["__load", "__navigate", "__window", "__debug", "__contextMenu"];
|
|
22
|
+
class WoodRouter {
|
|
23
|
+
// IoC Container
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
26
|
+
this.reservedHandlers = /* @__PURE__ */ new Map();
|
|
27
|
+
this.container = options.container;
|
|
28
|
+
this.validator = new SchemaValidator();
|
|
29
|
+
this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);
|
|
30
|
+
this.controllerResolver = new ControllerResolver(options.controllersDir, {
|
|
31
|
+
mode: options.mode
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load operations from a parsed operations map.
|
|
36
|
+
*/
|
|
37
|
+
loadOperations(operations) {
|
|
38
|
+
for (const [channel, opDef] of operations) {
|
|
39
|
+
this.operations.set(channel, opDef);
|
|
40
|
+
}
|
|
41
|
+
logger.debug(`Loaded ${operations.size} operations`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Register a handler for a reserved channel (__load, __navigate, __window).
|
|
45
|
+
* These channels are internal to Wood and serve as extension points for
|
|
46
|
+
* the loader runner, navigation system, and window manager.
|
|
47
|
+
*/
|
|
48
|
+
registerReservedHandler(channel, handler) {
|
|
49
|
+
this.reservedHandlers.set(channel, handler);
|
|
50
|
+
logger.debug(`Registered reserved handler for "${channel}"`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register IPC handlers for all operations and reserved channels.
|
|
54
|
+
* In production: registers with ipcMain.handle
|
|
55
|
+
* In testing/bridge mode: handlers are callable via dispatch()
|
|
56
|
+
*/
|
|
57
|
+
registerIpcHandlers(ipcMain) {
|
|
58
|
+
for (const channel of this.operations.keys()) {
|
|
59
|
+
ipcMain.handle(channel, async (_event, data) => {
|
|
60
|
+
return this.dispatch(channel, data, _event);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
for (const channel of RESERVED_CHANNELS) {
|
|
64
|
+
ipcMain.handle(channel, async (_event, data) => {
|
|
65
|
+
const handler = this.reservedHandlers.get(channel);
|
|
66
|
+
if (!handler) {
|
|
67
|
+
throw new Error(`No handler registered for reserved channel "${channel}"`);
|
|
68
|
+
}
|
|
69
|
+
return handler(data, _event);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
logger.debug(
|
|
73
|
+
`Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The request lifecycle -- mirrors Dinner's pipeline.
|
|
78
|
+
*
|
|
79
|
+
* channel -> build context -> middleware -> validate -> resolve controller
|
|
80
|
+
* -> create instance -> build args -> call action -> return result
|
|
81
|
+
*/
|
|
82
|
+
async dispatch(channel, data, event) {
|
|
83
|
+
const opDef = this.operations.get(channel);
|
|
84
|
+
if (!opDef) {
|
|
85
|
+
throw new Error(`Unknown operation: "${channel}"`);
|
|
86
|
+
}
|
|
87
|
+
const conversationId = extractTraceConversationId(data);
|
|
88
|
+
publishMainTrace("debug", {
|
|
89
|
+
source: "wood.router",
|
|
90
|
+
type: "dispatch.start",
|
|
91
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
92
|
+
payload: {
|
|
93
|
+
channel,
|
|
94
|
+
controller: opDef.controller,
|
|
95
|
+
action: opDef.action
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
const ipcContext = {
|
|
99
|
+
body: data ?? {},
|
|
100
|
+
params: data ?? {},
|
|
101
|
+
query: {},
|
|
102
|
+
context: {},
|
|
103
|
+
sender: event?.sender,
|
|
104
|
+
windowId: void 0
|
|
105
|
+
};
|
|
106
|
+
if (opDef.middleware.length > 0) {
|
|
107
|
+
const mwContext = buildMiddlewareContext(ipcContext, channel);
|
|
108
|
+
const middlewareFns = await Promise.all(
|
|
109
|
+
opDef.middleware.map((spec) => this.middlewareResolver.resolve(spec))
|
|
110
|
+
);
|
|
111
|
+
await executeMiddleware(middlewareFns, mwContext);
|
|
112
|
+
}
|
|
113
|
+
if (opDef.inputSchema) {
|
|
114
|
+
const result = this.validator.validate(
|
|
115
|
+
channel,
|
|
116
|
+
opDef.inputSchema,
|
|
117
|
+
ipcContext.body
|
|
118
|
+
);
|
|
119
|
+
if (!result.valid) {
|
|
120
|
+
return {
|
|
121
|
+
error: "VALIDATION_ERROR",
|
|
122
|
+
message: "Request validation failed",
|
|
123
|
+
details: result.errors
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);
|
|
128
|
+
const scopedContainer = this.container.extend();
|
|
129
|
+
const instance = await scopedContainer.instance(ControllerClass);
|
|
130
|
+
const args = buildControllerArgs(ipcContext, scopedContainer);
|
|
131
|
+
const action = instance[opDef.action];
|
|
132
|
+
if (typeof action !== "function") {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`Controller "${opDef.controller}" has no action "${opDef.action}"`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const result = await action.call(instance, args);
|
|
139
|
+
publishMainTrace("debug", {
|
|
140
|
+
source: "wood.router",
|
|
141
|
+
type: "dispatch.success",
|
|
142
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
143
|
+
payload: {
|
|
144
|
+
channel,
|
|
145
|
+
controller: opDef.controller,
|
|
146
|
+
action: opDef.action
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return result;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
publishMainTrace("error", {
|
|
152
|
+
source: "wood.router",
|
|
153
|
+
type: "dispatch.error",
|
|
154
|
+
message: error instanceof Error ? error.message : String(error),
|
|
155
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
156
|
+
payload: {
|
|
157
|
+
channel,
|
|
158
|
+
controller: opDef.controller,
|
|
159
|
+
action: opDef.action
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Pre-register a controller class by name so it is resolved from
|
|
167
|
+
* the in-memory cache instead of the filesystem.
|
|
168
|
+
* This is the public API used by the generated registration file.
|
|
169
|
+
*/
|
|
170
|
+
registerController(name, ControllerClass) {
|
|
171
|
+
this.controllerResolver.register(name, ControllerClass);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Register an import path for a controller. The controller will be lazily
|
|
175
|
+
* imported from this path when first needed, avoiding circular dependencies.
|
|
176
|
+
*/
|
|
177
|
+
registerControllerPath(name, importPath) {
|
|
178
|
+
this.controllerResolver.registerPath(name, importPath);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Validate that every controller referenced in loaded operations is
|
|
182
|
+
* pre-registered in the controller resolver. Call this after
|
|
183
|
+
* loadOperations() + registerControllers() but before registerIpcHandlers().
|
|
184
|
+
*
|
|
185
|
+
* Throws with a clear error listing all missing controllers if any
|
|
186
|
+
* operation references a controller that was not pre-registered.
|
|
187
|
+
*/
|
|
188
|
+
validateControllers() {
|
|
189
|
+
const missing = [];
|
|
190
|
+
for (const [channel, opDef] of this.operations) {
|
|
191
|
+
if (!this.controllerResolver.has(opDef.controller)) {
|
|
192
|
+
missing.push({ channel, controller: opDef.controller });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (missing.length > 0) {
|
|
196
|
+
const details = missing.map((m) => ` - channel "${m.channel}" requires controller "${m.controller}"`).join("\n");
|
|
197
|
+
throw new Error(
|
|
198
|
+
`WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.
|
|
199
|
+
This usually means controllers.generated.ts is missing or out of date.
|
|
200
|
+
Run "npx wood build" or "npx wood dev" to regenerate it.
|
|
201
|
+
|
|
202
|
+
Missing controllers:
|
|
203
|
+
${details}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
logger.info(`All ${this.operations.size} operations have registered controllers`);
|
|
207
|
+
}
|
|
208
|
+
/** Get all registered operation channels. */
|
|
209
|
+
getChannels() {
|
|
210
|
+
return Array.from(this.operations.keys());
|
|
211
|
+
}
|
|
212
|
+
/** Get a specific operation definition. */
|
|
213
|
+
getOperation(channel) {
|
|
214
|
+
return this.operations.get(channel);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
RESERVED_CHANNELS,
|
|
219
|
+
WoodRouter
|
|
220
|
+
};
|
|
221
|
+
//# sourceMappingURL=wood_router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.js';\nimport { SchemaValidator } from '../validation/schema_validator.js';\nimport { MiddlewareResolver } from '../middleware/middleware_resolver.js';\nimport { buildMiddlewareContext, executeMiddleware } from '../middleware/middleware_pipeline.js';\nimport { ControllerResolver, buildControllerArgs } from '../controller/controller_resolver.js';\nimport { getLogger } from '@noego/logger';\nimport { publishMainTrace } from '../tracing/index.js';\n\nconst logger = getLogger('wood:router');\n\nfunction extractTraceConversationId(value: unknown): number | string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n if (typeof record.conversationId === 'number' || typeof record.conversationId === 'string') {\n return record.conversationId;\n }\n if (typeof record.threadId === 'number' || typeof record.threadId === 'string') {\n return record.threadId;\n }\n\n return undefined;\n}\n\n/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */\nexport const RESERVED_CHANNELS = ['__load', '__navigate', '__window', '__debug', '__contextMenu'] as const;\nexport type ReservedChannel = (typeof RESERVED_CHANNELS)[number];\n\n/** Handler signature for reserved channels. */\nexport type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;\n\nexport class WoodRouter {\n private operations = new Map<string, OperationDef>();\n private reservedHandlers = new Map<ReservedChannel, ReservedChannelHandler>();\n private validator: SchemaValidator;\n private middlewareResolver: MiddlewareResolver;\n private controllerResolver: ControllerResolver;\n private container: any; // IoC Container\n\n constructor(options: {\n container: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n }) {\n this.container = options.container;\n this.validator = new SchemaValidator();\n this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);\n this.controllerResolver = new ControllerResolver(options.controllersDir, {\n mode: options.mode,\n });\n }\n\n /**\n * Load operations from a parsed operations map.\n */\n loadOperations(operations: Map<string, OperationDef>): void {\n for (const [channel, opDef] of operations) {\n this.operations.set(channel, opDef);\n }\n logger.debug(`Loaded ${operations.size} operations`);\n }\n\n /**\n * Register a handler for a reserved channel (__load, __navigate, __window).\n * These channels are internal to Wood and serve as extension points for\n * the loader runner, navigation system, and window manager.\n */\n registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void {\n this.reservedHandlers.set(channel, handler);\n logger.debug(`Registered reserved handler for \"${channel}\"`);\n }\n\n /**\n * Register IPC handlers for all operations and reserved channels.\n * In production: registers with ipcMain.handle\n * In testing/bridge mode: handlers are callable via dispatch()\n */\n registerIpcHandlers(ipcMain: any): void {\n for (const channel of this.operations.keys()) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n return this.dispatch(channel, data, _event);\n });\n }\n\n // Register reserved channels\n for (const channel of RESERVED_CHANNELS) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n const handler = this.reservedHandlers.get(channel);\n if (!handler) {\n throw new Error(`No handler registered for reserved channel \"${channel}\"`);\n }\n return handler(data, _event);\n });\n }\n\n logger.debug(\n `Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`\n );\n }\n\n /**\n * The request lifecycle -- mirrors Dinner's pipeline.\n *\n * channel -> build context -> middleware -> validate -> resolve controller\n * -> create instance -> build args -> call action -> return result\n */\n async dispatch(channel: string, data: unknown, event?: any): Promise<unknown> {\n const opDef = this.operations.get(channel);\n if (!opDef) {\n throw new Error(`Unknown operation: \"${channel}\"`);\n }\n\n const conversationId = extractTraceConversationId(data);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.start',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n\n // 1. Build IPC context\n const ipcContext: IpcContext = {\n body: data ?? {},\n params: (data as any) ?? {},\n query: {},\n context: {},\n sender: event?.sender,\n windowId: undefined,\n };\n\n // 2. Execute middleware sequentially\n if (opDef.middleware.length > 0) {\n const mwContext = buildMiddlewareContext(ipcContext, channel);\n const middlewareFns = await Promise.all(\n opDef.middleware.map(spec => this.middlewareResolver.resolve(spec))\n );\n await executeMiddleware(middlewareFns, mwContext);\n }\n\n // 3. Validate input (if schema defined)\n if (opDef.inputSchema) {\n const result = this.validator.validate(\n channel,\n opDef.inputSchema as Record<string, unknown>,\n ipcContext.body\n );\n if (!result.valid) {\n return {\n error: 'VALIDATION_ERROR',\n message: 'Request validation failed',\n details: result.errors,\n };\n }\n }\n\n // 4. Resolve controller class (cached)\n const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);\n\n // 5. Create instance via IoC (per-request scoped container)\n const scopedContainer = this.container.extend();\n const instance = await scopedContainer.instance(ControllerClass);\n\n // 6. Build controller args (fake req/res)\n const args = buildControllerArgs(ipcContext, scopedContainer);\n\n // 7. Call action, return result\n const action = instance[opDef.action];\n if (typeof action !== 'function') {\n throw new Error(\n `Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`\n );\n }\n\n try {\n const result = await action.call(instance, args);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.success',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n return result;\n } catch (error) {\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.error',\n message: error instanceof Error ? error.message : String(error),\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n throw error;\n }\n }\n\n /**\n * Pre-register a controller class by name so it is resolved from\n * the in-memory cache instead of the filesystem.\n * This is the public API used by the generated registration file.\n */\n registerController(name: string, ControllerClass: any): void {\n this.controllerResolver.register(name, ControllerClass);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed, avoiding circular dependencies.\n */\n registerControllerPath(name: string, importPath: string): void {\n this.controllerResolver.registerPath(name, importPath);\n }\n\n /**\n * Validate that every controller referenced in loaded operations is\n * pre-registered in the controller resolver. Call this after\n * loadOperations() + registerControllers() but before registerIpcHandlers().\n *\n * Throws with a clear error listing all missing controllers if any\n * operation references a controller that was not pre-registered.\n */\n validateControllers(): void {\n const missing: Array<{ channel: string; controller: string }> = [];\n\n for (const [channel, opDef] of this.operations) {\n if (!this.controllerResolver.has(opDef.controller)) {\n missing.push({ channel, controller: opDef.controller });\n }\n }\n\n if (missing.length > 0) {\n const details = missing\n .map(m => ` - channel \"${m.channel}\" requires controller \"${m.controller}\"`)\n .join('\\n');\n\n throw new Error(\n `WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.\\n` +\n `This usually means controllers.generated.ts is missing or out of date.\\n` +\n `Run \"npx wood build\" or \"npx wood dev\" to regenerate it.\\n\\n` +\n `Missing controllers:\\n${details}`\n );\n }\n\n logger.info(`All ${this.operations.size} operations have registered controllers`);\n }\n\n /** Get all registered operation channels. */\n getChannels(): string[] {\n return Array.from(this.operations.keys());\n }\n\n /** Get a specific operation definition. */\n getOperation(channel: string): OperationDef | undefined {\n return this.operations.get(channel);\n }\n}\n"],"mappings":"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","names":[]}
|