@noego/wood 0.4.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -42
- package/bin/axe.js +313 -98
- package/dist/{loader/__fixtures__/layouts/app.load.cjs → automation/actions.cjs} +3 -13
- package/dist/automation/actions.cjs.map +1 -0
- package/dist/automation/actions.d.cts +57 -0
- package/dist/automation/actions.d.ts +57 -0
- package/dist/automation/actions.js +1 -0
- package/dist/automation/actions.js.map +1 -0
- package/dist/automation/actions_executor.cjs +101 -0
- package/dist/automation/actions_executor.cjs.map +1 -0
- package/dist/automation/actions_executor.d.cts +16 -0
- package/dist/automation/actions_executor.d.ts +16 -0
- package/dist/automation/actions_executor.js +76 -0
- package/dist/automation/actions_executor.js.map +1 -0
- package/dist/automation/connection.cjs +86 -0
- package/dist/automation/connection.cjs.map +1 -0
- package/dist/automation/connection.d.cts +18 -0
- package/dist/automation/connection.d.ts +18 -0
- package/dist/automation/connection.js +51 -0
- package/dist/automation/connection.js.map +1 -0
- package/dist/{middleware/__fixtures__/middleware/sequence.cjs → automation/errors.cjs} +25 -22
- package/dist/automation/errors.cjs.map +1 -0
- package/dist/automation/errors.d.cts +31 -0
- package/dist/automation/errors.d.ts +31 -0
- package/dist/automation/errors.js +24 -0
- package/dist/automation/errors.js.map +1 -0
- package/dist/automation/index.cjs +49 -0
- package/dist/automation/index.cjs.map +1 -0
- package/dist/automation/index.d.cts +16 -0
- package/dist/automation/index.d.ts +16 -0
- package/dist/automation/index.js +15 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/introspection_reader.cjs +75 -0
- package/dist/automation/introspection_reader.cjs.map +1 -0
- package/dist/automation/introspection_reader.d.cts +20 -0
- package/dist/automation/introspection_reader.d.ts +20 -0
- package/dist/automation/introspection_reader.js +48 -0
- package/dist/automation/introspection_reader.js.map +1 -0
- package/dist/automation/locator.cjs +102 -0
- package/dist/automation/locator.cjs.map +1 -0
- package/dist/automation/locator.d.cts +51 -0
- package/dist/automation/locator.d.ts +51 -0
- package/dist/automation/locator.js +75 -0
- package/dist/automation/locator.js.map +1 -0
- package/dist/{loader/__fixtures__/views/test/page.load.cjs → automation/observation.cjs} +3 -13
- package/dist/automation/observation.cjs.map +1 -0
- package/dist/automation/observation.d.cts +44 -0
- package/dist/automation/observation.d.ts +44 -0
- package/dist/automation/observation.js +1 -0
- package/dist/automation/observation.js.map +1 -0
- package/dist/{controller/__fixtures__/controllers/test.cjs → automation/receipts.cjs} +3 -15
- package/dist/automation/receipts.cjs.map +1 -0
- package/dist/automation/receipts.d.cts +27 -0
- package/dist/automation/receipts.d.ts +27 -0
- package/dist/automation/receipts.js +1 -0
- package/dist/automation/receipts.js.map +1 -0
- package/dist/automation/scenario.cjs +696 -0
- package/dist/automation/scenario.cjs.map +1 -0
- package/dist/automation/scenario.d.cts +89 -0
- package/dist/automation/scenario.d.ts +89 -0
- package/dist/automation/scenario.js +660 -0
- package/dist/automation/scenario.js.map +1 -0
- package/dist/automation/scrolling.cjs +17 -0
- package/dist/automation/scrolling.cjs.map +1 -0
- package/dist/automation/scrolling.d.cts +51 -0
- package/dist/automation/scrolling.d.ts +51 -0
- package/dist/automation/scrolling.js +1 -0
- package/dist/automation/scrolling.js.map +1 -0
- package/dist/automation/scrolling_executor.cjs +109 -0
- package/dist/automation/scrolling_executor.cjs.map +1 -0
- package/dist/automation/scrolling_executor.d.cts +13 -0
- package/dist/automation/scrolling_executor.d.ts +13 -0
- package/dist/automation/scrolling_executor.js +84 -0
- package/dist/automation/scrolling_executor.js.map +1 -0
- package/dist/automation/target_identity.cjs +17 -0
- package/dist/automation/target_identity.cjs.map +1 -0
- package/dist/automation/target_identity.d.cts +28 -0
- package/dist/automation/target_identity.d.ts +28 -0
- package/dist/automation/target_identity.js +1 -0
- package/dist/automation/target_identity.js.map +1 -0
- package/dist/automation/target_registry.cjs +148 -0
- package/dist/automation/target_registry.cjs.map +1 -0
- package/dist/automation/target_registry.d.cts +32 -0
- package/dist/automation/target_registry.d.ts +32 -0
- package/dist/automation/target_registry.js +122 -0
- package/dist/automation/target_registry.js.map +1 -0
- package/dist/automation/waits.cjs +17 -0
- package/dist/automation/waits.cjs.map +1 -0
- package/dist/automation/waits.d.cts +44 -0
- package/dist/automation/waits.d.ts +44 -0
- package/dist/automation/waits.js +1 -0
- package/dist/automation/waits.js.map +1 -0
- package/dist/automation/waits_executor.cjs +104 -0
- package/dist/automation/waits_executor.cjs.map +1 -0
- package/dist/automation/waits_executor.d.cts +14 -0
- package/dist/automation/waits_executor.d.ts +14 -0
- package/dist/automation/waits_executor.js +79 -0
- package/dist/automation/waits_executor.js.map +1 -0
- package/dist/bridge/backend_bridge.cjs.map +1 -1
- package/dist/bridge/backend_bridge.js.map +1 -1
- package/dist/client/index.cjs +78 -21
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +19 -3
- package/dist/client/index.d.ts +19 -3
- package/dist/client/index.js +80 -22
- package/dist/client/index.js.map +1 -1
- package/dist/client/renderer_log_transport.cjs +151 -0
- package/dist/client/renderer_log_transport.cjs.map +1 -0
- package/dist/client/renderer_log_transport.d.cts +54 -0
- package/dist/client/renderer_log_transport.d.ts +54 -0
- package/dist/client/renderer_log_transport.js +123 -0
- package/dist/client/renderer_log_transport.js.map +1 -0
- package/dist/codegen/controller_registration_generator.cjs +13 -2
- package/dist/codegen/controller_registration_generator.cjs.map +1 -1
- package/dist/codegen/controller_registration_generator.d.cts +12 -1
- package/dist/codegen/controller_registration_generator.d.ts +12 -1
- package/dist/codegen/controller_registration_generator.js +10 -1
- package/dist/codegen/controller_registration_generator.js.map +1 -1
- package/dist/codegen/index.d.cts +1 -0
- package/dist/codegen/index.d.ts +1 -0
- package/dist/codegen/preload_generator.cjs +13 -6
- package/dist/codegen/preload_generator.cjs.map +1 -1
- package/dist/codegen/preload_generator.d.cts +11 -2
- package/dist/codegen/preload_generator.d.ts +11 -2
- package/dist/codegen/preload_generator.js +13 -6
- package/dist/codegen/preload_generator.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +95 -44
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +95 -44
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/codegen/type_generator.cjs +1 -0
- package/dist/codegen/type_generator.cjs.map +1 -1
- package/dist/codegen/type_generator.js +1 -0
- package/dist/codegen/type_generator.js.map +1 -1
- package/dist/config/config_parser.cjs +95 -4
- package/dist/config/config_parser.cjs.map +1 -1
- package/dist/config/config_parser.d.cts +10 -2
- package/dist/config/config_parser.d.ts +10 -2
- package/dist/config/config_parser.js +92 -3
- package/dist/config/config_parser.js.map +1 -1
- package/dist/config/index.cjs +6 -2
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.cts +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +8 -2
- package/dist/config/index.js.map +1 -1
- package/dist/controller/controller_resolver.cjs +51 -3
- package/dist/controller/controller_resolver.cjs.map +1 -1
- package/dist/controller/controller_resolver.d.cts +27 -4
- package/dist/controller/controller_resolver.d.ts +27 -4
- package/dist/controller/controller_resolver.js +48 -2
- package/dist/controller/controller_resolver.js.map +1 -1
- package/dist/controller/index.cjs +6 -2
- package/dist/controller/index.cjs.map +1 -1
- package/dist/controller/index.d.cts +1 -1
- package/dist/controller/index.d.ts +1 -1
- package/dist/controller/index.js +4 -2
- package/dist/controller/index.js.map +1 -1
- package/dist/dev/wood_dev_server.cjs +4 -1
- package/dist/dev/wood_dev_server.cjs.map +1 -1
- package/dist/dev/wood_dev_server.js +5 -2
- package/dist/dev/wood_dev_server.js.map +1 -1
- package/dist/dev/yaml_watcher.cjs +1 -1
- package/dist/dev/yaml_watcher.cjs.map +1 -1
- package/dist/dev/yaml_watcher.d.cts +4 -0
- package/dist/dev/yaml_watcher.d.ts +4 -0
- package/dist/dev/yaml_watcher.js +1 -1
- package/dist/dev/yaml_watcher.js.map +1 -1
- package/dist/frontend/frontend_lifecycle.cjs +74 -0
- package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
- package/dist/frontend/frontend_lifecycle.d.cts +50 -0
- package/dist/frontend/frontend_lifecycle.d.ts +50 -0
- package/dist/frontend/frontend_lifecycle.js +50 -0
- package/dist/frontend/frontend_lifecycle.js.map +1 -0
- package/dist/frontend/frontend_page.cjs +122 -0
- package/dist/frontend/frontend_page.cjs.map +1 -0
- package/dist/frontend/frontend_page.d.cts +62 -0
- package/dist/frontend/frontend_page.d.ts +62 -0
- package/dist/frontend/frontend_page.js +98 -0
- package/dist/frontend/frontend_page.js.map +1 -0
- package/dist/frontend/frontend_surface.cjs +249 -0
- package/dist/frontend/frontend_surface.cjs.map +1 -0
- package/dist/frontend/frontend_surface.d.cts +64 -0
- package/dist/frontend/frontend_surface.d.ts +64 -0
- package/dist/frontend/frontend_surface.js +224 -0
- package/dist/frontend/frontend_surface.js.map +1 -0
- package/dist/frontend/index.cjs +52 -0
- package/dist/frontend/index.cjs.map +1 -0
- package/dist/frontend/index.d.cts +10 -0
- package/dist/frontend/index.d.ts +10 -0
- package/dist/frontend/index.js +19 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/page_catalog.cjs +135 -0
- package/dist/frontend/page_catalog.cjs.map +1 -0
- package/dist/frontend/page_catalog.d.cts +56 -0
- package/dist/frontend/page_catalog.d.ts +56 -0
- package/dist/frontend/page_catalog.js +108 -0
- package/dist/frontend/page_catalog.js.map +1 -0
- package/dist/frontend/tracked_transport.cjs +55 -0
- package/dist/frontend/tracked_transport.cjs.map +1 -0
- package/dist/frontend/tracked_transport.d.cts +36 -0
- package/dist/frontend/tracked_transport.d.ts +36 -0
- package/dist/frontend/tracked_transport.js +31 -0
- package/dist/frontend/tracked_transport.js.map +1 -0
- package/dist/frontend/work_registry.cjs +153 -0
- package/dist/frontend/work_registry.cjs.map +1 -0
- package/dist/frontend/work_registry.d.cts +70 -0
- package/dist/frontend/work_registry.d.ts +70 -0
- package/dist/frontend/work_registry.js +128 -0
- package/dist/frontend/work_registry.js.map +1 -0
- package/dist/index.cjs +24 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/dist/main/index.cjs +10 -0
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +14 -2
- package/dist/main/index.d.ts +14 -2
- package/dist/main/index.js +16 -0
- package/dist/main/index.js.map +1 -1
- package/dist/middleware/middleware_resolver.cjs +22 -1
- package/dist/middleware/middleware_resolver.cjs.map +1 -1
- package/dist/middleware/middleware_resolver.d.cts +13 -1
- package/dist/middleware/middleware_resolver.d.ts +13 -1
- package/dist/middleware/middleware_resolver.js +22 -1
- package/dist/middleware/middleware_resolver.js.map +1 -1
- package/dist/navigation/automation_introspection.cjs +110 -0
- package/dist/navigation/automation_introspection.cjs.map +1 -0
- package/dist/navigation/automation_introspection.d.cts +60 -0
- package/dist/navigation/automation_introspection.d.ts +60 -0
- package/dist/navigation/automation_introspection.js +85 -0
- package/dist/navigation/automation_introspection.js.map +1 -0
- package/dist/navigation/index.cjs +10 -2
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +27 -1
- package/dist/navigation/index.d.ts +27 -1
- package/dist/navigation/index.js +6 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
- package/dist/navigation/layout_preservation.cjs.map +1 -0
- package/dist/navigation/layout_preservation.d.cts +2 -0
- package/dist/navigation/layout_preservation.d.ts +2 -0
- package/dist/navigation/layout_preservation.js +18 -0
- package/dist/navigation/layout_preservation.js.map +1 -0
- package/dist/parser/index.cjs +2 -0
- package/dist/parser/index.cjs.map +1 -1
- package/dist/parser/index.d.cts +1 -1
- package/dist/parser/index.d.ts +1 -1
- package/dist/parser/index.js +2 -1
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/operations_parser.cjs +6 -0
- package/dist/parser/operations_parser.cjs.map +1 -1
- package/dist/parser/operations_parser.d.cts +9 -2
- package/dist/parser/operations_parser.d.ts +9 -2
- package/dist/parser/operations_parser.js +5 -0
- package/dist/parser/operations_parser.js.map +1 -1
- package/dist/parser/views_parser.cjs.map +1 -1
- package/dist/parser/views_parser.js.map +1 -1
- package/dist/router/index.d.cts +1 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/router/wood_router.cjs +35 -3
- package/dist/router/wood_router.cjs.map +1 -1
- package/dist/router/wood_router.d.cts +15 -0
- package/dist/router/wood_router.d.ts +15 -0
- package/dist/router/wood_router.js +36 -4
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/get_container.cjs +9 -34
- package/dist/runtime/get_container.cjs.map +1 -1
- package/dist/runtime/get_container.d.cts +24 -4
- package/dist/runtime/get_container.d.ts +24 -4
- package/dist/runtime/get_container.js +8 -23
- package/dist/runtime/get_container.js.map +1 -1
- package/dist/runtime/index.cjs +9 -0
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +5 -2
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +10 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderer_config_extension.cjs +50 -0
- package/dist/runtime/renderer_config_extension.cjs.map +1 -0
- package/dist/runtime/renderer_config_extension.d.cts +19 -0
- package/dist/runtime/renderer_config_extension.d.ts +19 -0
- package/dist/runtime/renderer_config_extension.js +24 -0
- package/dist/runtime/renderer_config_extension.js.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.js +48 -0
- package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
- package/dist/runtime/runtime.cjs +14 -0
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +2 -1
- package/dist/runtime/runtime.d.ts +2 -1
- package/dist/runtime/runtime.js +14 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/stick/index.cjs.map +1 -1
- package/dist/stick/index.js.map +1 -1
- package/dist/testing/automation_assertions.cjs +417 -0
- package/dist/testing/automation_assertions.cjs.map +1 -0
- package/dist/testing/automation_assertions.d.cts +44 -0
- package/dist/testing/automation_assertions.d.ts +44 -0
- package/dist/testing/automation_assertions.js +385 -0
- package/dist/testing/automation_assertions.js.map +1 -0
- package/dist/testing/browser.cjs +130 -57
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +10 -4
- package/dist/testing/browser.d.ts +10 -4
- package/dist/testing/browser.js +132 -53
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.cjs +28 -8
- package/dist/testing/create_controller_harness.cjs.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +18 -2
- package/dist/testing/create_controller_harness.d.ts +18 -2
- package/dist/testing/create_controller_harness.js +28 -8
- package/dist/testing/create_controller_harness.js.map +1 -1
- package/dist/testing/create_router_bridge.d.cts +1 -0
- package/dist/testing/create_router_bridge.d.ts +1 -0
- package/dist/testing/create_test_router.d.cts +1 -0
- package/dist/testing/create_test_router.d.ts +1 -0
- package/dist/testing/geometry.cjs +109 -0
- package/dist/testing/geometry.cjs.map +1 -0
- package/dist/testing/geometry.d.cts +45 -0
- package/dist/testing/geometry.d.ts +45 -0
- package/dist/testing/geometry.js +79 -0
- package/dist/testing/geometry.js.map +1 -0
- package/dist/testing/index.cjs +62 -2
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +23 -4
- package/dist/testing/index.d.ts +23 -4
- package/dist/testing/index.js +50 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
- package/dist/testing/test_wood.cjs.map +1 -0
- package/dist/testing/test_wood.d.cts +16 -0
- package/dist/testing/test_wood.d.ts +16 -0
- package/dist/testing/test_wood.js +12 -0
- package/dist/testing/test_wood.js.map +1 -0
- package/dist/testing/test_wood_config.cjs +272 -0
- package/dist/testing/test_wood_config.cjs.map +1 -0
- package/dist/testing/test_wood_config.d.cts +111 -0
- package/dist/testing/test_wood_config.d.ts +111 -0
- package/dist/testing/test_wood_config.js +247 -0
- package/dist/testing/test_wood_config.js.map +1 -0
- package/dist/testing/wood_config_source.cjs +146 -0
- package/dist/testing/wood_config_source.cjs.map +1 -0
- package/dist/testing/wood_config_source.d.cts +36 -0
- package/dist/testing/wood_config_source.d.ts +36 -0
- package/dist/testing/wood_config_source.js +112 -0
- package/dist/testing/wood_config_source.js.map +1 -0
- package/dist/testing/wood_env_renderer.cjs +210 -0
- package/dist/testing/wood_env_renderer.cjs.map +1 -0
- package/dist/testing/wood_env_renderer.d.cts +74 -0
- package/dist/testing/wood_env_renderer.d.ts +74 -0
- package/dist/testing/wood_env_renderer.js +188 -0
- package/dist/testing/wood_env_renderer.js.map +1 -0
- package/dist/testing/wood_test_selection.cjs +94 -0
- package/dist/testing/wood_test_selection.cjs.map +1 -0
- package/dist/testing/wood_test_selection.d.cts +39 -0
- package/dist/testing/wood_test_selection.d.ts +39 -0
- package/dist/testing/wood_test_selection.js +68 -0
- package/dist/testing/wood_test_selection.js.map +1 -0
- package/dist/trace-testing/index.d.cts +1 -2
- package/dist/trace-testing/index.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.cjs +1 -1
- package/dist/trace-testing/trace_recorder.cjs.map +1 -1
- package/dist/trace-testing/trace_recorder.d.cts +1 -2
- package/dist/trace-testing/trace_recorder.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.js +1 -1
- package/dist/trace-testing/trace_recorder.js.map +1 -1
- package/dist/trace-transport/index.d.cts +1 -1
- package/dist/trace-transport/index.d.ts +1 -1
- package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
- package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
- package/dist/tracing/index.cjs +9 -2
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +3 -2
- package/dist/tracing/index.d.ts +3 -2
- package/dist/tracing/index.js +7 -1
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
- package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
- package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
- package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.js +48 -6
- package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
- package/dist/tracing/trace_batch_adapter.cjs +110 -0
- package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
- package/dist/tracing/trace_batch_adapter.d.cts +36 -0
- package/dist/tracing/trace_batch_adapter.d.ts +36 -0
- package/dist/tracing/trace_batch_adapter.js +86 -0
- package/dist/tracing/trace_batch_adapter.js.map +1 -0
- package/dist/tracing/trace_commit_writer.d.cts +1 -1
- package/dist/tracing/trace_commit_writer.d.ts +1 -1
- package/dist/tracing/trace_hub.cjs +87 -20
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +1 -1
- package/dist/tracing/trace_hub.d.ts +1 -1
- package/dist/tracing/trace_hub.js +85 -20
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +21 -6
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +13 -4
- package/dist/tracing/trace_provider.d.ts +13 -4
- package/dist/tracing/trace_provider.js +22 -7
- package/dist/tracing/trace_provider.js.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
- package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
- package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
- package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
- package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.js +2 -0
- package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
- package/dist/transport/build_transport_bridge.cjs +4 -2
- package/dist/transport/build_transport_bridge.cjs.map +1 -1
- package/dist/transport/build_transport_bridge.d.cts +7 -1
- package/dist/transport/build_transport_bridge.d.ts +7 -1
- package/dist/transport/build_transport_bridge.js +2 -1
- package/dist/transport/build_transport_bridge.js.map +1 -1
- package/dist/transport/in_process_router_transport.d.cts +1 -0
- package/dist/transport/in_process_router_transport.d.ts +1 -0
- package/dist/transport/index.d.cts +1 -0
- package/dist/transport/index.d.ts +1 -0
- package/dist/types/config.cjs.map +1 -1
- package/dist/types/config.d.cts +47 -1
- package/dist/types/config.d.ts +47 -1
- package/dist/types/context.cjs +12 -0
- package/dist/types/context.cjs.map +1 -1
- package/dist/types/context.d.cts +27 -1
- package/dist/types/context.d.ts +27 -1
- package/dist/types/context.js +4 -0
- package/dist/types/context.js.map +1 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/operations.cjs.map +1 -1
- package/dist/types/operations.d.cts +2 -0
- package/dist/types/operations.d.ts +2 -0
- package/docs/axe.md +706 -0
- package/package.json +19 -5
- package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
- package/src/components/NavigationShell.svelte +126 -49
- package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.js +0 -12
- package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
- package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
- package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
- package/dist/controller/__fixtures__/controllers/test.js +0 -9
- package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
- package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
- package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
- package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
- package/dist/middleware/__fixtures__/middleware/sequence.js.map +0 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const EXTENSION_SYMBOL = /* @__PURE__ */ Symbol.for("@noego/wood.runtime.renderer-config-extension");
|
|
2
|
+
function setRendererConfigExtension(extension) {
|
|
3
|
+
globalThis[EXTENSION_SYMBOL] = extension;
|
|
4
|
+
}
|
|
5
|
+
function getRendererConfigExtension() {
|
|
6
|
+
return globalThis[EXTENSION_SYMBOL] ?? null;
|
|
7
|
+
}
|
|
8
|
+
async function resolveRendererConfigExtension() {
|
|
9
|
+
const extension = getRendererConfigExtension();
|
|
10
|
+
if (!extension) return {};
|
|
11
|
+
try {
|
|
12
|
+
const value = await extension();
|
|
13
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
|
|
14
|
+
return { ...value };
|
|
15
|
+
} catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
getRendererConfigExtension,
|
|
21
|
+
resolveRendererConfigExtension,
|
|
22
|
+
setRendererConfigExtension
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=renderer_config_extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/renderer_config_extension.ts"],"sourcesContent":["const EXTENSION_SYMBOL = Symbol.for('@noego/wood.runtime.renderer-config-extension');\n\n/**\n * App-supplied provider of extra fields merged into the `__woodConfig` payload\n * the renderer fetches at boot. Lets the main process hand renderers boot-time\n * facts Wood itself knows nothing about — e.g. the loopback port and per-boot\n * token of an external log sink — without a new IPC channel or preload method.\n *\n * Reserved Wood keys (rendererTrace*, appEnv) always win over extension keys.\n */\nexport type RendererConfigExtension = () =>\n | Readonly<Record<string, unknown>>\n | Promise<Readonly<Record<string, unknown>>>;\n\ntype GlobalWithExtension = typeof globalThis & {\n [EXTENSION_SYMBOL]?: RendererConfigExtension | null;\n};\n\nexport function setRendererConfigExtension(extension: RendererConfigExtension | null): void {\n (globalThis as GlobalWithExtension)[EXTENSION_SYMBOL] = extension;\n}\n\nexport function getRendererConfigExtension(): RendererConfigExtension | null {\n return (globalThis as GlobalWithExtension)[EXTENSION_SYMBOL] ?? null;\n}\n\n/**\n * Resolves the extension fields for one `__woodConfig` request. A throwing or\n * malformed extension yields `{}` — config delivery must never fail the\n * renderer boot because of an app-side provider.\n */\nexport async function resolveRendererConfigExtension(): Promise<Record<string, unknown>> {\n const extension = getRendererConfigExtension();\n if (!extension) return {};\n try {\n const value = await extension();\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return {};\n return { ...value };\n } catch {\n return {};\n }\n}\n"],"mappings":"AAAA,MAAM,mBAAmB,uBAAO,IAAI,+CAA+C;AAkB5E,SAAS,2BAA2B,WAAiD;AAC1F,EAAC,WAAmC,gBAAgB,IAAI;AAC1D;AAEO,SAAS,6BAA6D;AAC3E,SAAQ,WAAmC,gBAAgB,KAAK;AAClE;AAOA,eAAsB,iCAAmE;AACvF,QAAM,YAAY,2BAA2B;AAC7C,MAAI,CAAC,UAAW,QAAO,CAAC;AACxB,MAAI;AACF,UAAM,QAAQ,MAAM,UAAU;AAC9B,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACjF,WAAO,EAAE,GAAG,MAAM;AAAA,EACpB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
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 renderer_log_batch_receiver_exports = {};
|
|
20
|
+
__export(renderer_log_batch_receiver_exports, {
|
|
21
|
+
dispatchRendererLogBatch: () => dispatchRendererLogBatch,
|
|
22
|
+
setRendererLogRecordFilter: () => setRendererLogRecordFilter
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(renderer_log_batch_receiver_exports);
|
|
25
|
+
var import_logger = require("@noego/logger");
|
|
26
|
+
var import_stream = require("@noego/trace/stream");
|
|
27
|
+
const FILTER_SYMBOL = /* @__PURE__ */ Symbol.for("@noego/wood.runtime.renderer-log-record-filter");
|
|
28
|
+
function setRendererLogRecordFilter(filter) {
|
|
29
|
+
globalThis[FILTER_SYMBOL] = filter;
|
|
30
|
+
}
|
|
31
|
+
function isValidRecord(value) {
|
|
32
|
+
if (typeof value !== "object" || value === null) return false;
|
|
33
|
+
const r = value;
|
|
34
|
+
return typeof r.id === "string" && Number.isFinite(r.occurredAtMs) && typeof r.producerId === "string" && Number.isSafeInteger(r.sequence) && typeof r.level === "string" && typeof r.logger === "string" && typeof r.message === "string" && typeof r.service === "string" && typeof r.environment === "string";
|
|
35
|
+
}
|
|
36
|
+
function dispatchRendererLogBatch(rawPayload) {
|
|
37
|
+
let records;
|
|
38
|
+
try {
|
|
39
|
+
records = (0, import_stream.unwrapRecordBatch)(rawPayload);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
ingested: 0,
|
|
44
|
+
filtered: 0,
|
|
45
|
+
reason: "malformed-batch",
|
|
46
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
for (const record of records) {
|
|
50
|
+
if (!isValidRecord(record)) {
|
|
51
|
+
return { ok: false, ingested: 0, filtered: 0, reason: "malformed-record" };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const filter = globalThis[FILTER_SYMBOL] ?? null;
|
|
55
|
+
const manager = (0, import_logger.getManager)();
|
|
56
|
+
let ingested = 0;
|
|
57
|
+
let filtered = 0;
|
|
58
|
+
for (const record of records) {
|
|
59
|
+
if (filter && !filter(record)) {
|
|
60
|
+
filtered += 1;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
manager.ingest(Object.freeze({ ...record }));
|
|
64
|
+
ingested += 1;
|
|
65
|
+
}
|
|
66
|
+
return { ok: true, ingested, filtered };
|
|
67
|
+
}
|
|
68
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
69
|
+
0 && (module.exports = {
|
|
70
|
+
dispatchRendererLogBatch,
|
|
71
|
+
setRendererLogRecordFilter
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=renderer_log_batch_receiver.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/renderer_log_batch_receiver.ts"],"sourcesContent":["import { getManager, type LogRecord } from '@noego/logger';\nimport { unwrapRecordBatch, type RecordBatch } from '@noego/trace/stream';\n\nconst FILTER_SYMBOL = Symbol.for('@noego/wood.runtime.renderer-log-record-filter');\n\n/**\n * Optional app-installed predicate applied to each received renderer record\n * before it is merged into the main process log stream. Return false to drop\n * (e.g. known-noise ResizeObserver loop errors). Filtering never rewrites the\n * record.\n */\nexport type RendererLogRecordFilter = (record: LogRecord) => boolean;\n\ntype GlobalWithFilter = typeof globalThis & {\n [FILTER_SYMBOL]?: RendererLogRecordFilter | null;\n};\n\nexport function setRendererLogRecordFilter(filter: RendererLogRecordFilter | null): void {\n (globalThis as GlobalWithFilter)[FILTER_SYMBOL] = filter;\n}\n\nexport type RendererLogBatchResult = {\n ok: boolean;\n ingested: number;\n filtered: number;\n reason?: 'malformed-batch' | 'malformed-record';\n errorMessage?: string;\n};\n\nfunction isValidRecord(value: unknown): value is LogRecord {\n if (typeof value !== 'object' || value === null) return false;\n const r = value as Record<string, unknown>;\n return typeof r.id === 'string'\n && Number.isFinite(r.occurredAtMs)\n && typeof r.producerId === 'string'\n && Number.isSafeInteger(r.sequence)\n && typeof r.level === 'string'\n && typeof r.logger === 'string'\n && typeof r.message === 'string'\n && typeof r.service === 'string'\n && typeof r.environment === 'string';\n}\n\n/**\n * Receives one renderer log batch from the __log_batch IPC channel: validates\n * the envelope, verifies each record's admitted shape, applies the optional\n * app filter, and merges surviving records into the main process stream via\n * LoggingManager.ingest — identity and occurredAtMs preserved exactly.\n *\n * A malformed envelope or record rejects the batch whole (mirrors\n * unwrapRecordBatch semantics: never partially merge a corrupt batch).\n */\nexport function dispatchRendererLogBatch(rawPayload: unknown): RendererLogBatchResult {\n let records: readonly LogRecord[];\n try {\n records = unwrapRecordBatch(rawPayload as RecordBatch<LogRecord>);\n } catch (error) {\n return {\n ok: false,\n ingested: 0,\n filtered: 0,\n reason: 'malformed-batch',\n errorMessage: error instanceof Error ? error.message : String(error),\n };\n }\n\n for (const record of records) {\n if (!isValidRecord(record)) {\n return { ok: false, ingested: 0, filtered: 0, reason: 'malformed-record' };\n }\n }\n\n const filter = (globalThis as GlobalWithFilter)[FILTER_SYMBOL] ?? null;\n const manager = getManager();\n let ingested = 0;\n let filtered = 0;\n for (const record of records) {\n if (filter && !filter(record)) {\n filtered += 1;\n continue;\n }\n manager.ingest(Object.freeze({ ...record }) as LogRecord);\n ingested += 1;\n }\n\n return { ok: true, ingested, filtered };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA2C;AAC3C,oBAAoD;AAEpD,MAAM,gBAAgB,uBAAO,IAAI,gDAAgD;AAc1E,SAAS,2BAA2B,QAA8C;AACvF,EAAC,WAAgC,aAAa,IAAI;AACpD;AAUA,SAAS,cAAc,OAAoC;AACzD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,SAAO,OAAO,EAAE,OAAO,YAClB,OAAO,SAAS,EAAE,YAAY,KAC9B,OAAO,EAAE,eAAe,YACxB,OAAO,cAAc,EAAE,QAAQ,KAC/B,OAAO,EAAE,UAAU,YACnB,OAAO,EAAE,WAAW,YACpB,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,gBAAgB;AAChC;AAWO,SAAS,yBAAyB,YAA6C;AACpF,MAAI;AACJ,MAAI;AACF,kBAAU,iCAAkB,UAAoC;AAAA,EAClE,SAAS,OAAO;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,cAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IACrE;AAAA,EACF;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,aAAO,EAAE,IAAI,OAAO,UAAU,GAAG,UAAU,GAAG,QAAQ,mBAAmB;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,SAAU,WAAgC,aAAa,KAAK;AAClE,QAAM,cAAU,0BAAW;AAC3B,MAAI,WAAW;AACf,MAAI,WAAW;AACf,aAAW,UAAU,SAAS;AAC5B,QAAI,UAAU,CAAC,OAAO,MAAM,GAAG;AAC7B,kBAAY;AACZ;AAAA,IACF;AACA,YAAQ,OAAO,OAAO,OAAO,EAAE,GAAG,OAAO,CAAC,CAAc;AACxD,gBAAY;AAAA,EACd;AAEA,SAAO,EAAE,IAAI,MAAM,UAAU,SAAS;AACxC;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LogRecord } from '@noego/logger';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Optional app-installed predicate applied to each received renderer record
|
|
5
|
+
* before it is merged into the main process log stream. Return false to drop
|
|
6
|
+
* (e.g. known-noise ResizeObserver loop errors). Filtering never rewrites the
|
|
7
|
+
* record.
|
|
8
|
+
*/
|
|
9
|
+
type RendererLogRecordFilter = (record: LogRecord) => boolean;
|
|
10
|
+
declare function setRendererLogRecordFilter(filter: RendererLogRecordFilter | null): void;
|
|
11
|
+
type RendererLogBatchResult = {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
ingested: number;
|
|
14
|
+
filtered: number;
|
|
15
|
+
reason?: 'malformed-batch' | 'malformed-record';
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Receives one renderer log batch from the __log_batch IPC channel: validates
|
|
20
|
+
* the envelope, verifies each record's admitted shape, applies the optional
|
|
21
|
+
* app filter, and merges surviving records into the main process stream via
|
|
22
|
+
* LoggingManager.ingest — identity and occurredAtMs preserved exactly.
|
|
23
|
+
*
|
|
24
|
+
* A malformed envelope or record rejects the batch whole (mirrors
|
|
25
|
+
* unwrapRecordBatch semantics: never partially merge a corrupt batch).
|
|
26
|
+
*/
|
|
27
|
+
declare function dispatchRendererLogBatch(rawPayload: unknown): RendererLogBatchResult;
|
|
28
|
+
|
|
29
|
+
export { type RendererLogBatchResult, type RendererLogRecordFilter, dispatchRendererLogBatch, setRendererLogRecordFilter };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LogRecord } from '@noego/logger';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Optional app-installed predicate applied to each received renderer record
|
|
5
|
+
* before it is merged into the main process log stream. Return false to drop
|
|
6
|
+
* (e.g. known-noise ResizeObserver loop errors). Filtering never rewrites the
|
|
7
|
+
* record.
|
|
8
|
+
*/
|
|
9
|
+
type RendererLogRecordFilter = (record: LogRecord) => boolean;
|
|
10
|
+
declare function setRendererLogRecordFilter(filter: RendererLogRecordFilter | null): void;
|
|
11
|
+
type RendererLogBatchResult = {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
ingested: number;
|
|
14
|
+
filtered: number;
|
|
15
|
+
reason?: 'malformed-batch' | 'malformed-record';
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Receives one renderer log batch from the __log_batch IPC channel: validates
|
|
20
|
+
* the envelope, verifies each record's admitted shape, applies the optional
|
|
21
|
+
* app filter, and merges surviving records into the main process stream via
|
|
22
|
+
* LoggingManager.ingest — identity and occurredAtMs preserved exactly.
|
|
23
|
+
*
|
|
24
|
+
* A malformed envelope or record rejects the batch whole (mirrors
|
|
25
|
+
* unwrapRecordBatch semantics: never partially merge a corrupt batch).
|
|
26
|
+
*/
|
|
27
|
+
declare function dispatchRendererLogBatch(rawPayload: unknown): RendererLogBatchResult;
|
|
28
|
+
|
|
29
|
+
export { type RendererLogBatchResult, type RendererLogRecordFilter, dispatchRendererLogBatch, setRendererLogRecordFilter };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getManager } from "@noego/logger";
|
|
2
|
+
import { unwrapRecordBatch } from "@noego/trace/stream";
|
|
3
|
+
const FILTER_SYMBOL = /* @__PURE__ */ Symbol.for("@noego/wood.runtime.renderer-log-record-filter");
|
|
4
|
+
function setRendererLogRecordFilter(filter) {
|
|
5
|
+
globalThis[FILTER_SYMBOL] = filter;
|
|
6
|
+
}
|
|
7
|
+
function isValidRecord(value) {
|
|
8
|
+
if (typeof value !== "object" || value === null) return false;
|
|
9
|
+
const r = value;
|
|
10
|
+
return typeof r.id === "string" && Number.isFinite(r.occurredAtMs) && typeof r.producerId === "string" && Number.isSafeInteger(r.sequence) && typeof r.level === "string" && typeof r.logger === "string" && typeof r.message === "string" && typeof r.service === "string" && typeof r.environment === "string";
|
|
11
|
+
}
|
|
12
|
+
function dispatchRendererLogBatch(rawPayload) {
|
|
13
|
+
let records;
|
|
14
|
+
try {
|
|
15
|
+
records = unwrapRecordBatch(rawPayload);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
ingested: 0,
|
|
20
|
+
filtered: 0,
|
|
21
|
+
reason: "malformed-batch",
|
|
22
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
for (const record of records) {
|
|
26
|
+
if (!isValidRecord(record)) {
|
|
27
|
+
return { ok: false, ingested: 0, filtered: 0, reason: "malformed-record" };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const filter = globalThis[FILTER_SYMBOL] ?? null;
|
|
31
|
+
const manager = getManager();
|
|
32
|
+
let ingested = 0;
|
|
33
|
+
let filtered = 0;
|
|
34
|
+
for (const record of records) {
|
|
35
|
+
if (filter && !filter(record)) {
|
|
36
|
+
filtered += 1;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
manager.ingest(Object.freeze({ ...record }));
|
|
40
|
+
ingested += 1;
|
|
41
|
+
}
|
|
42
|
+
return { ok: true, ingested, filtered };
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
dispatchRendererLogBatch,
|
|
46
|
+
setRendererLogRecordFilter
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=renderer_log_batch_receiver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/renderer_log_batch_receiver.ts"],"sourcesContent":["import { getManager, type LogRecord } from '@noego/logger';\nimport { unwrapRecordBatch, type RecordBatch } from '@noego/trace/stream';\n\nconst FILTER_SYMBOL = Symbol.for('@noego/wood.runtime.renderer-log-record-filter');\n\n/**\n * Optional app-installed predicate applied to each received renderer record\n * before it is merged into the main process log stream. Return false to drop\n * (e.g. known-noise ResizeObserver loop errors). Filtering never rewrites the\n * record.\n */\nexport type RendererLogRecordFilter = (record: LogRecord) => boolean;\n\ntype GlobalWithFilter = typeof globalThis & {\n [FILTER_SYMBOL]?: RendererLogRecordFilter | null;\n};\n\nexport function setRendererLogRecordFilter(filter: RendererLogRecordFilter | null): void {\n (globalThis as GlobalWithFilter)[FILTER_SYMBOL] = filter;\n}\n\nexport type RendererLogBatchResult = {\n ok: boolean;\n ingested: number;\n filtered: number;\n reason?: 'malformed-batch' | 'malformed-record';\n errorMessage?: string;\n};\n\nfunction isValidRecord(value: unknown): value is LogRecord {\n if (typeof value !== 'object' || value === null) return false;\n const r = value as Record<string, unknown>;\n return typeof r.id === 'string'\n && Number.isFinite(r.occurredAtMs)\n && typeof r.producerId === 'string'\n && Number.isSafeInteger(r.sequence)\n && typeof r.level === 'string'\n && typeof r.logger === 'string'\n && typeof r.message === 'string'\n && typeof r.service === 'string'\n && typeof r.environment === 'string';\n}\n\n/**\n * Receives one renderer log batch from the __log_batch IPC channel: validates\n * the envelope, verifies each record's admitted shape, applies the optional\n * app filter, and merges surviving records into the main process stream via\n * LoggingManager.ingest — identity and occurredAtMs preserved exactly.\n *\n * A malformed envelope or record rejects the batch whole (mirrors\n * unwrapRecordBatch semantics: never partially merge a corrupt batch).\n */\nexport function dispatchRendererLogBatch(rawPayload: unknown): RendererLogBatchResult {\n let records: readonly LogRecord[];\n try {\n records = unwrapRecordBatch(rawPayload as RecordBatch<LogRecord>);\n } catch (error) {\n return {\n ok: false,\n ingested: 0,\n filtered: 0,\n reason: 'malformed-batch',\n errorMessage: error instanceof Error ? error.message : String(error),\n };\n }\n\n for (const record of records) {\n if (!isValidRecord(record)) {\n return { ok: false, ingested: 0, filtered: 0, reason: 'malformed-record' };\n }\n }\n\n const filter = (globalThis as GlobalWithFilter)[FILTER_SYMBOL] ?? null;\n const manager = getManager();\n let ingested = 0;\n let filtered = 0;\n for (const record of records) {\n if (filter && !filter(record)) {\n filtered += 1;\n continue;\n }\n manager.ingest(Object.freeze({ ...record }) as LogRecord);\n ingested += 1;\n }\n\n return { ok: true, ingested, filtered };\n}\n"],"mappings":"AAAA,SAAS,kBAAkC;AAC3C,SAAS,yBAA2C;AAEpD,MAAM,gBAAgB,uBAAO,IAAI,gDAAgD;AAc1E,SAAS,2BAA2B,QAA8C;AACvF,EAAC,WAAgC,aAAa,IAAI;AACpD;AAUA,SAAS,cAAc,OAAoC;AACzD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,SAAO,OAAO,EAAE,OAAO,YAClB,OAAO,SAAS,EAAE,YAAY,KAC9B,OAAO,EAAE,eAAe,YACxB,OAAO,cAAc,EAAE,QAAQ,KAC/B,OAAO,EAAE,UAAU,YACnB,OAAO,EAAE,WAAW,YACpB,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,gBAAgB;AAChC;AAWO,SAAS,yBAAyB,YAA6C;AACpF,MAAI;AACJ,MAAI;AACF,cAAU,kBAAkB,UAAoC;AAAA,EAClE,SAAS,OAAO;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,cAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IACrE;AAAA,EACF;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,aAAO,EAAE,IAAI,OAAO,UAAU,GAAG,UAAU,GAAG,QAAQ,mBAAmB;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,SAAU,WAAgC,aAAa,KAAK;AAClE,QAAM,UAAU,WAAW;AAC3B,MAAI,WAAW;AACf,MAAI,WAAW;AACf,aAAW,UAAU,SAAS;AAC5B,QAAI,UAAU,CAAC,OAAO,MAAM,GAAG;AAC7B,kBAAY;AACZ;AAAA,IACF;AACA,YAAQ,OAAO,OAAO,OAAO,EAAE,GAAG,OAAO,CAAC,CAAc;AACxD,gBAAY;AAAA,EACd;AAEA,SAAO,EAAE,IAAI,MAAM,UAAU,SAAS;AACxC;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WoodTraceBatchReceiver } from '../tracing/types/wood_trace_batch.types.cjs';
|
|
2
2
|
import '@noego/telemetry/core';
|
|
3
|
-
import '../trace_hub-
|
|
3
|
+
import '../trace_hub-Cpo_nVze.cjs';
|
|
4
4
|
import 'rxjs';
|
|
5
5
|
|
|
6
6
|
declare function setRendererTraceBatchReceiver(receiver: WoodTraceBatchReceiver | null): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WoodTraceBatchReceiver } from '../tracing/types/wood_trace_batch.types.js';
|
|
2
2
|
import '@noego/telemetry/core';
|
|
3
|
-
import '../trace_hub-
|
|
3
|
+
import '../trace_hub-Cpo_nVze.js';
|
|
4
4
|
import 'rxjs';
|
|
5
5
|
|
|
6
6
|
declare function setRendererTraceBatchReceiver(receiver: WoodTraceBatchReceiver | null): void;
|
package/dist/runtime/runtime.cjs
CHANGED
|
@@ -27,6 +27,8 @@ var import_get_container = require("./get_container.cjs");
|
|
|
27
27
|
var import_tracing = require("../tracing/index.js");
|
|
28
28
|
var import_tracing2 = require("../tracing/index.js");
|
|
29
29
|
var import_renderer_log_dispatcher = require("./renderer_log_dispatcher.js");
|
|
30
|
+
var import_renderer_log_batch_receiver = require("./renderer_log_batch_receiver.js");
|
|
31
|
+
var import_renderer_config_extension = require("./renderer_config_extension.js");
|
|
30
32
|
var import_renderer_trace_batch_receiver_registry = require("./renderer_trace_batch_receiver_registry.js");
|
|
31
33
|
var import_app_env = require("./app_env.js");
|
|
32
34
|
const logger = (0, import_logger.getLogger)("wood:runtime");
|
|
@@ -137,6 +139,8 @@ function registerReservedRuntimeHandlers(router, options, settings, rendererTrac
|
|
|
137
139
|
requireRuntimeHandler("__contextMenu", "onContextMenu", options.onContextMenu)
|
|
138
140
|
);
|
|
139
141
|
router.registerReservedHandler("__woodConfig", async () => ({
|
|
142
|
+
// App extension fields first so Wood's reserved keys always win.
|
|
143
|
+
...await (0, import_renderer_config_extension.resolveRendererConfigExtension)(),
|
|
140
144
|
rendererTraceEnabled: settings.rendererTraceEnabled,
|
|
141
145
|
rendererTraceMinLevel: settings.rendererTraceMinLevel,
|
|
142
146
|
rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,
|
|
@@ -187,6 +191,16 @@ function registerRendererLogBridge(ipcMain) {
|
|
|
187
191
|
}
|
|
188
192
|
});
|
|
189
193
|
});
|
|
194
|
+
ipcMain.removeAllListeners?.("__log_batch");
|
|
195
|
+
ipcMain.on("__log_batch", (_event, rawPayload) => {
|
|
196
|
+
const result = (0, import_renderer_log_batch_receiver.dispatchRendererLogBatch)(rawPayload);
|
|
197
|
+
if (!result.ok) {
|
|
198
|
+
logger.warn("renderer log batch rejected", {
|
|
199
|
+
reason: result.reason ?? null,
|
|
200
|
+
errorMessage: result.errorMessage ?? null
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
190
204
|
logger.info("renderer log bridge registered (fire-and-forget)");
|
|
191
205
|
}
|
|
192
206
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.cjs';\nimport { getContainer } from './get_container.cjs';\nimport {\n RendererTraceBatchHost,\n TraceProviderConfiguration,\n dispatchRendererTracePayload,\n} from '../tracing/index.js';\nimport {\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n type TraceLevel,\n type TraceRuntimeContext,\n type WoodTraceBatchReceiver,\n} from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\nimport { getRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.js';\nimport { resolveWoodAppEnv, type WoodAppEnv } from './app_env.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n /** Override the resolved app environment tier reported to renderers via __woodConfig. */\n appEnv?: WoodAppEnv;\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n /** Resolves only with the acknowledgement produced by the downstream durable receiver. */\n rendererTraceBatchReceiver?: WoodTraceBatchReceiver;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n resolveRendererTraceContext?: (event: unknown) => TraceRuntimeContext | undefined;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\ntype RuntimeReservedHandler = (\n data: unknown,\n event?: unknown,\n) => Promise<unknown>;\n\ntype RuntimeTraceSettings = Readonly<{\n enableRendererLogBridge: boolean;\n enableRendererTraceBridge: boolean;\n traceMinLevel: TraceLevel | undefined;\n rendererTraceEnabled: boolean;\n rendererTraceMinLevel: TraceLevel;\n rendererTraceBatchEnabled: boolean;\n}>;\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (typeof level === 'string') {\n const normalized = level.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n rendererTraceEnabled = false,\n rendererTraceMinLevel = 'debug',\n } = options;\n\n const container = options.container ?? getContainer();\n const rendererTraceBatchReceiver = options.rendererTraceBatchReceiver\n ?? getRendererTraceBatchReceiver();\n const rendererTraceBatchEnabled = rendererTraceBatchReceiver !== null;\n const rendererTraceBatchHost = new RendererTraceBatchHost(\n rendererTraceBatchReceiver,\n );\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n });\n\n const traceSettings: RuntimeTraceSettings = {\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel,\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n };\n await configureRuntimeTracing(container, traceSettings);\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.precompileSchemas();\n logger.info('runtime schema pre-compilation complete');\n\n registerReservedRuntimeHandlers(router, options, traceSettings, rendererTraceBatchHost);\n registerRuntimeObservationBridges(ipcMain, traceSettings, options.resolveRendererTraceContext);\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nasync function configureRuntimeTracing(\n container: any,\n settings: RuntimeTraceSettings,\n): Promise<void> {\n if (settings.traceMinLevel) {\n setMainTraceMinLevel(settings.traceMinLevel);\n }\n setRendererTraceMinLevel(settings.rendererTraceMinLevel);\n if (typeof container.instance !== 'function') {\n return;\n }\n\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (settings.traceMinLevel) {\n traceConfiguration.configureMinLevel(settings.traceMinLevel);\n }\n}\n\nfunction registerReservedRuntimeHandlers(\n router: WoodRouter,\n options: RuntimeOptions,\n settings: RuntimeTraceSettings,\n rendererTraceBatchHost: RendererTraceBatchHost,\n): void {\n router.registerReservedHandler('__load', requireRuntimeHandler('__load', 'onLoad', options.onLoad));\n router.registerReservedHandler('__navigate', requireRuntimeHandler('__navigate', 'onNavigate', options.onNavigate));\n router.registerReservedHandler('__window', requireRuntimeHandler('__window', 'onWindow', options.onWindow));\n router.registerReservedHandler('__debug', requireRuntimeHandler('__debug', 'onDebug', options.onDebug));\n router.registerReservedHandler(\n '__contextMenu',\n requireRuntimeHandler('__contextMenu', 'onContextMenu', options.onContextMenu),\n );\n router.registerReservedHandler('__woodConfig', async () => ({\n rendererTraceEnabled: settings.rendererTraceEnabled,\n rendererTraceMinLevel: settings.rendererTraceMinLevel,\n rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,\n appEnv: options.appEnv ?? await resolveWoodAppEnv(),\n }));\n router.registerReservedHandler('__traceBatch', async (data, event) => {\n return rendererTraceBatchHost.receive(data, options.resolveRendererTraceContext?.(event) ?? {});\n });\n}\n\nfunction registerRuntimeObservationBridges(\n ipcMain: IpcMainLike,\n settings: RuntimeTraceSettings,\n resolveContext: RuntimeOptions['resolveRendererTraceContext'],\n): void {\n if (settings.enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n ipcMain.removeAllListeners?.('__trace');\n if (settings.enableRendererTraceBridge && settings.rendererTraceEnabled) {\n registerRendererTraceBridge(ipcMain, resolveContext);\n }\n}\n\nfunction requireRuntimeHandler(\n channel: string,\n optionName: string,\n handler: RuntimeReservedHandler | undefined,\n): RuntimeReservedHandler {\n return async (data, event) => {\n if (!handler) {\n throw new Error(`Reserved channel \"${channel}\" not configured. Provide runtime({ ${optionName} }).`);\n }\n return handler(data, event);\n };\n}\n\nfunction registerRendererTraceBridge(\n ipcMain: IpcMainLike,\n resolveContext?: (event: unknown) => TraceRuntimeContext | undefined,\n): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload, resolveContext?.(event));\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":["import_tracing"]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.cjs';\nimport { getContainer } from './get_container.cjs';\nimport {\n RendererTraceBatchHost,\n TraceProviderConfiguration,\n dispatchRendererTracePayload,\n} from '../tracing/index.js';\nimport {\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n type TraceLevel,\n type TraceRuntimeContext,\n type WoodTraceBatchReceiver,\n} from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\nimport { dispatchRendererLogBatch } from './renderer_log_batch_receiver.js';\nimport { resolveRendererConfigExtension } from './renderer_config_extension.js';\nimport { getRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.js';\nimport { resolveWoodAppEnv, type WoodAppEnv } from './app_env.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n /** Override the resolved app environment tier reported to renderers via __woodConfig. */\n appEnv?: WoodAppEnv;\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n /** Resolves only with the acknowledgement produced by the downstream durable receiver. */\n rendererTraceBatchReceiver?: WoodTraceBatchReceiver;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n resolveRendererTraceContext?: (event: unknown) => TraceRuntimeContext | undefined;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\ntype RuntimeReservedHandler = (\n data: unknown,\n event?: unknown,\n) => Promise<unknown>;\n\ntype RuntimeTraceSettings = Readonly<{\n enableRendererLogBridge: boolean;\n enableRendererTraceBridge: boolean;\n traceMinLevel: TraceLevel | undefined;\n rendererTraceEnabled: boolean;\n rendererTraceMinLevel: TraceLevel;\n rendererTraceBatchEnabled: boolean;\n}>;\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (typeof level === 'string') {\n const normalized = level.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n rendererTraceEnabled = false,\n rendererTraceMinLevel = 'debug',\n } = options;\n\n const container = options.container ?? getContainer();\n const rendererTraceBatchReceiver = options.rendererTraceBatchReceiver\n ?? getRendererTraceBatchReceiver();\n const rendererTraceBatchEnabled = rendererTraceBatchReceiver !== null;\n const rendererTraceBatchHost = new RendererTraceBatchHost(\n rendererTraceBatchReceiver,\n );\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n });\n\n const traceSettings: RuntimeTraceSettings = {\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel,\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n };\n await configureRuntimeTracing(container, traceSettings);\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.precompileSchemas();\n logger.info('runtime schema pre-compilation complete');\n\n registerReservedRuntimeHandlers(router, options, traceSettings, rendererTraceBatchHost);\n registerRuntimeObservationBridges(ipcMain, traceSettings, options.resolveRendererTraceContext);\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nasync function configureRuntimeTracing(\n container: any,\n settings: RuntimeTraceSettings,\n): Promise<void> {\n if (settings.traceMinLevel) {\n setMainTraceMinLevel(settings.traceMinLevel);\n }\n setRendererTraceMinLevel(settings.rendererTraceMinLevel);\n if (typeof container.instance !== 'function') {\n return;\n }\n\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (settings.traceMinLevel) {\n traceConfiguration.configureMinLevel(settings.traceMinLevel);\n }\n}\n\nfunction registerReservedRuntimeHandlers(\n router: WoodRouter,\n options: RuntimeOptions,\n settings: RuntimeTraceSettings,\n rendererTraceBatchHost: RendererTraceBatchHost,\n): void {\n router.registerReservedHandler('__load', requireRuntimeHandler('__load', 'onLoad', options.onLoad));\n router.registerReservedHandler('__navigate', requireRuntimeHandler('__navigate', 'onNavigate', options.onNavigate));\n router.registerReservedHandler('__window', requireRuntimeHandler('__window', 'onWindow', options.onWindow));\n router.registerReservedHandler('__debug', requireRuntimeHandler('__debug', 'onDebug', options.onDebug));\n router.registerReservedHandler(\n '__contextMenu',\n requireRuntimeHandler('__contextMenu', 'onContextMenu', options.onContextMenu),\n );\n router.registerReservedHandler('__woodConfig', async () => ({\n // App extension fields first so Wood's reserved keys always win.\n ...(await resolveRendererConfigExtension()),\n rendererTraceEnabled: settings.rendererTraceEnabled,\n rendererTraceMinLevel: settings.rendererTraceMinLevel,\n rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,\n appEnv: options.appEnv ?? await resolveWoodAppEnv(),\n }));\n router.registerReservedHandler('__traceBatch', async (data, event) => {\n return rendererTraceBatchHost.receive(data, options.resolveRendererTraceContext?.(event) ?? {});\n });\n}\n\nfunction registerRuntimeObservationBridges(\n ipcMain: IpcMainLike,\n settings: RuntimeTraceSettings,\n resolveContext: RuntimeOptions['resolveRendererTraceContext'],\n): void {\n if (settings.enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n ipcMain.removeAllListeners?.('__trace');\n if (settings.enableRendererTraceBridge && settings.rendererTraceEnabled) {\n registerRendererTraceBridge(ipcMain, resolveContext);\n }\n}\n\nfunction requireRuntimeHandler(\n channel: string,\n optionName: string,\n handler: RuntimeReservedHandler | undefined,\n): RuntimeReservedHandler {\n return async (data, event) => {\n if (!handler) {\n throw new Error(`Reserved channel \"${channel}\" not configured. Provide runtime({ ${optionName} }).`);\n }\n return handler(data, event);\n };\n}\n\nfunction registerRendererTraceBridge(\n ipcMain: IpcMainLike,\n resolveContext?: (event: unknown) => TraceRuntimeContext | undefined,\n): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload, resolveContext?.(event));\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n ipcMain.removeAllListeners?.('__log_batch');\n\n ipcMain.on('__log_batch', (_event, rawPayload) => {\n const result = dispatchRendererLogBatch(rawPayload);\n if (!result.ok) {\n logger.warn('renderer log batch rejected', {\n reason: result.reason ?? null,\n errorMessage: result.errorMessage ?? null,\n });\n }\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":["import_tracing"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { WoodRouter } from '../router/wood_router.cjs';
|
|
2
|
-
import { c as TraceLevel, e as TraceRuntimeContext } from '../trace_hub-
|
|
2
|
+
import { c as TraceLevel, e as TraceRuntimeContext } from '../trace_hub-Cpo_nVze.cjs';
|
|
3
3
|
import { WoodTraceBatchReceiver } from '../tracing/types/wood_trace_batch.types.cjs';
|
|
4
4
|
import { WoodAppEnv } from './app_env.cjs';
|
|
5
5
|
import '../types/operations.cjs';
|
|
6
|
+
import '../types/context.cjs';
|
|
6
7
|
import 'rxjs';
|
|
7
8
|
import '@noego/telemetry/core';
|
|
8
9
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { WoodRouter } from '../router/wood_router.js';
|
|
2
|
-
import { c as TraceLevel, e as TraceRuntimeContext } from '../trace_hub-
|
|
2
|
+
import { c as TraceLevel, e as TraceRuntimeContext } from '../trace_hub-Cpo_nVze.js';
|
|
3
3
|
import { WoodTraceBatchReceiver } from '../tracing/types/wood_trace_batch.types.js';
|
|
4
4
|
import { WoodAppEnv } from './app_env.js';
|
|
5
5
|
import '../types/operations.js';
|
|
6
|
+
import '../types/context.js';
|
|
6
7
|
import 'rxjs';
|
|
7
8
|
import '@noego/telemetry/core';
|
|
8
9
|
|
package/dist/runtime/runtime.js
CHANGED
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
getRendererLogDispatcher
|
|
15
15
|
} from "./renderer_log_dispatcher.js";
|
|
16
|
+
import { dispatchRendererLogBatch } from "./renderer_log_batch_receiver.js";
|
|
17
|
+
import { resolveRendererConfigExtension } from "./renderer_config_extension.js";
|
|
16
18
|
import { getRendererTraceBatchReceiver } from "./renderer_trace_batch_receiver_registry.js";
|
|
17
19
|
import { resolveWoodAppEnv } from "./app_env.js";
|
|
18
20
|
const logger = getLogger("wood:runtime");
|
|
@@ -123,6 +125,8 @@ function registerReservedRuntimeHandlers(router, options, settings, rendererTrac
|
|
|
123
125
|
requireRuntimeHandler("__contextMenu", "onContextMenu", options.onContextMenu)
|
|
124
126
|
);
|
|
125
127
|
router.registerReservedHandler("__woodConfig", async () => ({
|
|
128
|
+
// App extension fields first so Wood's reserved keys always win.
|
|
129
|
+
...await resolveRendererConfigExtension(),
|
|
126
130
|
rendererTraceEnabled: settings.rendererTraceEnabled,
|
|
127
131
|
rendererTraceMinLevel: settings.rendererTraceMinLevel,
|
|
128
132
|
rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,
|
|
@@ -173,6 +177,16 @@ function registerRendererLogBridge(ipcMain) {
|
|
|
173
177
|
}
|
|
174
178
|
});
|
|
175
179
|
});
|
|
180
|
+
ipcMain.removeAllListeners?.("__log_batch");
|
|
181
|
+
ipcMain.on("__log_batch", (_event, rawPayload) => {
|
|
182
|
+
const result = dispatchRendererLogBatch(rawPayload);
|
|
183
|
+
if (!result.ok) {
|
|
184
|
+
logger.warn("renderer log batch rejected", {
|
|
185
|
+
reason: result.reason ?? null,
|
|
186
|
+
errorMessage: result.errorMessage ?? null
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
176
190
|
logger.info("renderer log bridge registered (fire-and-forget)");
|
|
177
191
|
}
|
|
178
192
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.js';\nimport { getContainer } from './get_container.js';\nimport {\n RendererTraceBatchHost,\n TraceProviderConfiguration,\n dispatchRendererTracePayload,\n} from '../tracing/index.js';\nimport {\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n type TraceLevel,\n type TraceRuntimeContext,\n type WoodTraceBatchReceiver,\n} from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\nimport { getRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.js';\nimport { resolveWoodAppEnv, type WoodAppEnv } from './app_env.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n /** Override the resolved app environment tier reported to renderers via __woodConfig. */\n appEnv?: WoodAppEnv;\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n /** Resolves only with the acknowledgement produced by the downstream durable receiver. */\n rendererTraceBatchReceiver?: WoodTraceBatchReceiver;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n resolveRendererTraceContext?: (event: unknown) => TraceRuntimeContext | undefined;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\ntype RuntimeReservedHandler = (\n data: unknown,\n event?: unknown,\n) => Promise<unknown>;\n\ntype RuntimeTraceSettings = Readonly<{\n enableRendererLogBridge: boolean;\n enableRendererTraceBridge: boolean;\n traceMinLevel: TraceLevel | undefined;\n rendererTraceEnabled: boolean;\n rendererTraceMinLevel: TraceLevel;\n rendererTraceBatchEnabled: boolean;\n}>;\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (typeof level === 'string') {\n const normalized = level.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n rendererTraceEnabled = false,\n rendererTraceMinLevel = 'debug',\n } = options;\n\n const container = options.container ?? getContainer();\n const rendererTraceBatchReceiver = options.rendererTraceBatchReceiver\n ?? getRendererTraceBatchReceiver();\n const rendererTraceBatchEnabled = rendererTraceBatchReceiver !== null;\n const rendererTraceBatchHost = new RendererTraceBatchHost(\n rendererTraceBatchReceiver,\n );\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n });\n\n const traceSettings: RuntimeTraceSettings = {\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel,\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n };\n await configureRuntimeTracing(container, traceSettings);\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.precompileSchemas();\n logger.info('runtime schema pre-compilation complete');\n\n registerReservedRuntimeHandlers(router, options, traceSettings, rendererTraceBatchHost);\n registerRuntimeObservationBridges(ipcMain, traceSettings, options.resolveRendererTraceContext);\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nasync function configureRuntimeTracing(\n container: any,\n settings: RuntimeTraceSettings,\n): Promise<void> {\n if (settings.traceMinLevel) {\n setMainTraceMinLevel(settings.traceMinLevel);\n }\n setRendererTraceMinLevel(settings.rendererTraceMinLevel);\n if (typeof container.instance !== 'function') {\n return;\n }\n\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (settings.traceMinLevel) {\n traceConfiguration.configureMinLevel(settings.traceMinLevel);\n }\n}\n\nfunction registerReservedRuntimeHandlers(\n router: WoodRouter,\n options: RuntimeOptions,\n settings: RuntimeTraceSettings,\n rendererTraceBatchHost: RendererTraceBatchHost,\n): void {\n router.registerReservedHandler('__load', requireRuntimeHandler('__load', 'onLoad', options.onLoad));\n router.registerReservedHandler('__navigate', requireRuntimeHandler('__navigate', 'onNavigate', options.onNavigate));\n router.registerReservedHandler('__window', requireRuntimeHandler('__window', 'onWindow', options.onWindow));\n router.registerReservedHandler('__debug', requireRuntimeHandler('__debug', 'onDebug', options.onDebug));\n router.registerReservedHandler(\n '__contextMenu',\n requireRuntimeHandler('__contextMenu', 'onContextMenu', options.onContextMenu),\n );\n router.registerReservedHandler('__woodConfig', async () => ({\n rendererTraceEnabled: settings.rendererTraceEnabled,\n rendererTraceMinLevel: settings.rendererTraceMinLevel,\n rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,\n appEnv: options.appEnv ?? await resolveWoodAppEnv(),\n }));\n router.registerReservedHandler('__traceBatch', async (data, event) => {\n return rendererTraceBatchHost.receive(data, options.resolveRendererTraceContext?.(event) ?? {});\n });\n}\n\nfunction registerRuntimeObservationBridges(\n ipcMain: IpcMainLike,\n settings: RuntimeTraceSettings,\n resolveContext: RuntimeOptions['resolveRendererTraceContext'],\n): void {\n if (settings.enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n ipcMain.removeAllListeners?.('__trace');\n if (settings.enableRendererTraceBridge && settings.rendererTraceEnabled) {\n registerRendererTraceBridge(ipcMain, resolveContext);\n }\n}\n\nfunction requireRuntimeHandler(\n channel: string,\n optionName: string,\n handler: RuntimeReservedHandler | undefined,\n): RuntimeReservedHandler {\n return async (data, event) => {\n if (!handler) {\n throw new Error(`Reserved channel \"${channel}\" not configured. Provide runtime({ ${optionName} }).`);\n }\n return handler(data, event);\n };\n}\n\nfunction registerRendererTraceBridge(\n ipcMain: IpcMainLike,\n resolveContext?: (event: unknown) => TraceRuntimeContext | undefined,\n): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload, resolveContext?.(event));\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.js';\nimport { getContainer } from './get_container.js';\nimport {\n RendererTraceBatchHost,\n TraceProviderConfiguration,\n dispatchRendererTracePayload,\n} from '../tracing/index.js';\nimport {\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n type TraceLevel,\n type TraceRuntimeContext,\n type WoodTraceBatchReceiver,\n} from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\nimport { dispatchRendererLogBatch } from './renderer_log_batch_receiver.js';\nimport { resolveRendererConfigExtension } from './renderer_config_extension.js';\nimport { getRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.js';\nimport { resolveWoodAppEnv, type WoodAppEnv } from './app_env.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n /** Override the resolved app environment tier reported to renderers via __woodConfig. */\n appEnv?: WoodAppEnv;\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n rendererTraceEnabled?: boolean;\n rendererTraceMinLevel?: TraceLevel;\n /** Resolves only with the acknowledgement produced by the downstream durable receiver. */\n rendererTraceBatchReceiver?: WoodTraceBatchReceiver;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n resolveRendererTraceContext?: (event: unknown) => TraceRuntimeContext | undefined;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\ntype RuntimeReservedHandler = (\n data: unknown,\n event?: unknown,\n) => Promise<unknown>;\n\ntype RuntimeTraceSettings = Readonly<{\n enableRendererLogBridge: boolean;\n enableRendererTraceBridge: boolean;\n traceMinLevel: TraceLevel | undefined;\n rendererTraceEnabled: boolean;\n rendererTraceMinLevel: TraceLevel;\n rendererTraceBatchEnabled: boolean;\n}>;\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (typeof level === 'string') {\n const normalized = level.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n rendererTraceEnabled = false,\n rendererTraceMinLevel = 'debug',\n } = options;\n\n const container = options.container ?? getContainer();\n const rendererTraceBatchReceiver = options.rendererTraceBatchReceiver\n ?? getRendererTraceBatchReceiver();\n const rendererTraceBatchEnabled = rendererTraceBatchReceiver !== null;\n const rendererTraceBatchHost = new RendererTraceBatchHost(\n rendererTraceBatchReceiver,\n );\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n });\n\n const traceSettings: RuntimeTraceSettings = {\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel,\n rendererTraceEnabled,\n rendererTraceMinLevel,\n rendererTraceBatchEnabled,\n };\n await configureRuntimeTracing(container, traceSettings);\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.precompileSchemas();\n logger.info('runtime schema pre-compilation complete');\n\n registerReservedRuntimeHandlers(router, options, traceSettings, rendererTraceBatchHost);\n registerRuntimeObservationBridges(ipcMain, traceSettings, options.resolveRendererTraceContext);\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nasync function configureRuntimeTracing(\n container: any,\n settings: RuntimeTraceSettings,\n): Promise<void> {\n if (settings.traceMinLevel) {\n setMainTraceMinLevel(settings.traceMinLevel);\n }\n setRendererTraceMinLevel(settings.rendererTraceMinLevel);\n if (typeof container.instance !== 'function') {\n return;\n }\n\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (settings.traceMinLevel) {\n traceConfiguration.configureMinLevel(settings.traceMinLevel);\n }\n}\n\nfunction registerReservedRuntimeHandlers(\n router: WoodRouter,\n options: RuntimeOptions,\n settings: RuntimeTraceSettings,\n rendererTraceBatchHost: RendererTraceBatchHost,\n): void {\n router.registerReservedHandler('__load', requireRuntimeHandler('__load', 'onLoad', options.onLoad));\n router.registerReservedHandler('__navigate', requireRuntimeHandler('__navigate', 'onNavigate', options.onNavigate));\n router.registerReservedHandler('__window', requireRuntimeHandler('__window', 'onWindow', options.onWindow));\n router.registerReservedHandler('__debug', requireRuntimeHandler('__debug', 'onDebug', options.onDebug));\n router.registerReservedHandler(\n '__contextMenu',\n requireRuntimeHandler('__contextMenu', 'onContextMenu', options.onContextMenu),\n );\n router.registerReservedHandler('__woodConfig', async () => ({\n // App extension fields first so Wood's reserved keys always win.\n ...(await resolveRendererConfigExtension()),\n rendererTraceEnabled: settings.rendererTraceEnabled,\n rendererTraceMinLevel: settings.rendererTraceMinLevel,\n rendererTraceBatchEnabled: settings.rendererTraceBatchEnabled,\n appEnv: options.appEnv ?? await resolveWoodAppEnv(),\n }));\n router.registerReservedHandler('__traceBatch', async (data, event) => {\n return rendererTraceBatchHost.receive(data, options.resolveRendererTraceContext?.(event) ?? {});\n });\n}\n\nfunction registerRuntimeObservationBridges(\n ipcMain: IpcMainLike,\n settings: RuntimeTraceSettings,\n resolveContext: RuntimeOptions['resolveRendererTraceContext'],\n): void {\n if (settings.enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n ipcMain.removeAllListeners?.('__trace');\n if (settings.enableRendererTraceBridge && settings.rendererTraceEnabled) {\n registerRendererTraceBridge(ipcMain, resolveContext);\n }\n}\n\nfunction requireRuntimeHandler(\n channel: string,\n optionName: string,\n handler: RuntimeReservedHandler | undefined,\n): RuntimeReservedHandler {\n return async (data, event) => {\n if (!handler) {\n throw new Error(`Reserved channel \"${channel}\" not configured. Provide runtime({ ${optionName} }).`);\n }\n return handler(data, event);\n };\n}\n\nfunction registerRendererTraceBridge(\n ipcMain: IpcMainLike,\n resolveContext?: (event: unknown) => TraceRuntimeContext | undefined,\n): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload, resolveContext?.(event));\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n ipcMain.removeAllListeners?.('__log_batch');\n\n ipcMain.on('__log_batch', (_event, rawPayload) => {\n const result = dispatchRendererLogBatch(rawPayload);\n if (!result.ok) {\n logger.warn('renderer log batch rejected', {\n reason: result.reason ?? null,\n errorMessage: result.errorMessage ?? null,\n });\n }\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":[]}
|
package/dist/stick/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/stick/index.ts"],"sourcesContent":["import './allow_cli.cjs';\n// Type-only import — erased at runtime, won't trigger module loading\nimport type { WoodStaticRenderer } from './static_renderer.cjs';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { resolveImageRendererTemplate } from './template_resolver.cjs';\n\nexport type { WoodStaticRenderer };\nexport type {\n WoodStaticRendererConfig,\n WoodRenderOptions,\n WoodRenderToPageOptions,\n WoodRenderResult,\n} from './static_renderer';\n\n// ─────────────────────────────────────────────────────────────\n// Error Classes\n// ─────────────────────────────────────────────────────────────\n\nexport class PlaywrightNotInstalledError extends Error {\n name = 'PlaywrightNotInstalledError' as const;\n constructor() {\n super(\n 'ImageRenderer requires Playwright. Install it with:\\n' +\n ' npm install playwright\\n' +\n ' npx playwright install chromium'\n );\n }\n}\n\nexport class BrowserLaunchError extends Error {\n name = 'BrowserLaunchError' as const;\n constructor(message: string, public cause?: Error) {\n super(message);\n }\n}\n\nexport class RenderTimeoutError extends Error {\n name = 'RenderTimeoutError' as const;\n constructor(timeoutMs: number) {\n super(`Render timed out after ${timeoutMs}ms`);\n }\n}\n\nexport class RenderError extends Error {\n name = 'RenderError' as const;\n constructor(message: string, public cause?: Error) {\n super(message);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────\n\nexport interface ImageRendererConfig {\n /** Output directory for screenshots */\n outputDir: string;\n /** Default width (default: 1920) */\n width?: number;\n /** Default height (default: 1080) */\n height?: number;\n /** Device scale factor for retina (default: 1) */\n deviceScaleFactor?: number;\n /** Image format (default: 'png') */\n format?: 'png' | 'jpeg';\n /** JPEG quality 0-100 (default: 80) */\n quality?: number;\n /** Wait condition (default: 'networkidle') */\n waitUntil?: 'load' | 'domcontentloaded' | 'networkidle';\n /** Timeout in ms (default: 10000) */\n timeoutMs?: number;\n /** Custom HTML template with {{{HEAD}}}, {{{CSS}}}, {{{APP}}} placeholders */\n template?: string;\n\n // Static renderer config (one of these)\n /** Pre-created WoodStaticRenderer instance */\n staticRenderer?: WoodStaticRenderer;\n /** OR: Path to views.yaml */\n viewsConfig?: string;\n /**\n * Component directory (required if viewsConfig provided).\n * When template is omitted, stick auto-loads <componentDir>/index.html and\n * inlines <componentDir>/styles.css when present.\n */\n componentDir?: string;\n /** Asset path mappings (e.g., { '/images': ['public/images'] }) */\n assets?: Record<string, string[]>;\n}\n\nexport interface CaptureOptions {\n /** View component data */\n view?: any;\n /** Layout data (one object per layout) */\n layout?: any[];\n /** Wood bridge object passed as a prop to layouts and views */\n wood?: any;\n /** Override width */\n width?: number;\n /** Override height */\n height?: number;\n /** Capture full page (default: true) */\n fullPage?: boolean;\n /** Callback executed after page load, before screenshot. Receives the Playwright page object. */\n beforeCapture?: (page: any) => Promise<void>;\n}\n\nexport interface CaptureHtmlOptions {\n /** Override width */\n width?: number;\n /** Override height */\n height?: number;\n /** Capture full page (default: true) */\n fullPage?: boolean;\n /** Callback executed after page load, before screenshot. Receives the Playwright page object. */\n beforeCapture?: (page: any) => Promise<void>;\n}\n\ninterface CaptureResult {\n /** Raw image buffer */\n buffer: Buffer;\n /** Path where image was saved */\n path: string;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Playwright Loader\n// ─────────────────────────────────────────────────────────────\n\ntype PlaywrightModule = typeof import('playwright');\n\nasync function loadPlaywright(): Promise<PlaywrightModule> {\n try {\n const playwright = await import('playwright');\n return playwright;\n } catch {\n throw new PlaywrightNotInstalledError();\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Content Type Helper\n// ─────────────────────────────────────────────────────────────\n\nfunction getContentType(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n const types: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n };\n return types[ext] || 'application/octet-stream';\n}\n\n// ─────────────────────────────────────────────────────────────\n// ImageRenderer Class\n// ─────────────────────────────────────────────────────────────\n\nexport class ImageRenderer {\n private browser: any;\n private staticRenderer: WoodStaticRenderer;\n private config: Required<Omit<ImageRendererConfig, 'staticRenderer' | 'viewsConfig' | 'componentDir' | 'template' | 'assets'>> & {\n outputDir: string;\n template?: string;\n assets?: Record<string, string[]>;\n };\n\n constructor(\n browser: any,\n staticRenderer: WoodStaticRenderer,\n config: ImageRendererConfig\n ) {\n this.browser = browser;\n this.staticRenderer = staticRenderer;\n this.config = {\n outputDir: config.outputDir,\n width: config.width ?? 1920,\n height: config.height ?? 1080,\n deviceScaleFactor: config.deviceScaleFactor ?? 1,\n format: config.format ?? 'png',\n quality: config.quality ?? 80,\n waitUntil: config.waitUntil ?? 'networkidle',\n timeoutMs: config.timeoutMs ?? 10000,\n template: config.template,\n assets: config.assets,\n };\n }\n\n /**\n * Capture a view by dot-path key and save to outputDir\n */\n async capture(\n name: string,\n viewKey: string,\n options?: CaptureOptions\n ): Promise<CaptureResult> {\n const { view, layout, wood } = options ?? {};\n const html = await this.staticRenderer.renderToPage({\n viewKey,\n data: { view, layout },\n wood,\n template: this.config.template,\n });\n\n return this.captureHtmlInternal(name, html, options);\n }\n\n /**\n * Capture raw HTML and save to outputDir\n */\n async captureHtml(\n name: string,\n html: string,\n options?: CaptureHtmlOptions\n ): Promise<CaptureResult> {\n return this.captureHtmlInternal(name, html, options);\n }\n\n /**\n * Internal method to capture HTML to image\n */\n private async captureHtmlInternal(\n name: string,\n html: string,\n options?: CaptureHtmlOptions\n ): Promise<CaptureResult> {\n const width = options?.width ?? this.config.width;\n const height = options?.height ?? this.config.height;\n\n let context: any;\n let page: any;\n\n try {\n context = await this.browser.newContext({\n viewport: { width, height },\n deviceScaleFactor: this.config.deviceScaleFactor,\n });\n\n page = await context.newPage();\n\n // Route Interception Strategy:\n // We use page.goto() with a fake URL instead of page.setContent() because\n // setContent() has no base URL, so relative paths can't resolve.\n const FAKE_BASE_URL = 'http://stick-renderer/';\n\n await page.route(FAKE_BASE_URL, async (route: any) => {\n await route.fulfill({\n body: html,\n contentType: 'text/html',\n });\n });\n\n // Asset route interception\n if (this.config.assets) {\n for (const [urlPath, fsPaths] of Object.entries(this.config.assets)) {\n await page.route(`**${urlPath}/**`, async (route: any) => {\n const url = new URL(route.request().url());\n const relativePath = url.pathname.replace(urlPath, '');\n\n for (const fsPath of fsPaths) {\n const filePath = path.join(fsPath, relativePath);\n try {\n const body = await fs.promises.readFile(filePath);\n const contentType = getContentType(filePath);\n await route.fulfill({ body, contentType });\n return;\n } catch {\n // File not found in this path, try the next one\n }\n }\n\n await route.abort('filenotfound');\n });\n }\n }\n\n const waitUntilMapping = {\n 'load': 'load',\n 'domcontentloaded': 'domcontentloaded',\n 'networkidle': 'networkidle',\n } as const;\n\n try {\n await page.goto(FAKE_BASE_URL, {\n waitUntil: waitUntilMapping[this.config.waitUntil],\n timeout: this.config.timeoutMs,\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('timeout')) {\n throw new RenderTimeoutError(this.config.timeoutMs);\n }\n throw new RenderError(\n 'Failed to render HTML content',\n error instanceof Error ? error : undefined\n );\n }\n\n if (options?.beforeCapture) {\n await options.beforeCapture(page);\n }\n\n const screenshotOptions: {\n type: 'png' | 'jpeg';\n quality?: number;\n fullPage: boolean;\n } = {\n type: this.config.format,\n fullPage: options?.fullPage ?? true,\n };\n\n if (this.config.format === 'jpeg') {\n screenshotOptions.quality = this.config.quality;\n }\n\n const screenshot = await page.screenshot(screenshotOptions);\n const buffer = Buffer.from(screenshot);\n\n const filename = `${name}@${width}x${height}.${this.config.format}`;\n const outputPath = path.join(this.config.outputDir, filename);\n\n await fs.promises.mkdir(this.config.outputDir, { recursive: true });\n await fs.promises.writeFile(outputPath, buffer);\n\n return { buffer, path: outputPath };\n\n } finally {\n if (page) {\n await page.close().catch(() => {});\n }\n if (context) {\n await context.close().catch(() => {});\n }\n }\n }\n\n /**\n * Close browser and clean up resources\n */\n async close(): Promise<void> {\n if (this.browser) {\n await this.browser.close().catch(() => {});\n }\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Factory Function\n// ─────────────────────────────────────────────────────────────\n\nexport async function createImageRenderer(\n config: ImageRendererConfig\n): Promise<ImageRenderer> {\n const resolvedTemplate = resolveImageRendererTemplate({\n template: config.template,\n componentDir: config.componentDir,\n });\n const resolvedConfig: ImageRendererConfig = {\n ...config,\n template: resolvedTemplate,\n };\n\n const playwright = await loadPlaywright();\n\n let browser: any;\n try {\n browser = await playwright.chromium.launch({\n headless: true,\n });\n } catch (error) {\n throw new BrowserLaunchError(\n 'Failed to launch Chromium. Ensure it is installed with: npx playwright install chromium',\n error instanceof Error ? error : undefined\n );\n }\n\n let staticRenderer: WoodStaticRenderer;\n if (resolvedConfig.staticRenderer) {\n staticRenderer = resolvedConfig.staticRenderer;\n } else if (resolvedConfig.viewsConfig && resolvedConfig.componentDir) {\n const { createWoodStaticRenderer } = await import('./static_renderer.cjs');\n staticRenderer = createWoodStaticRenderer({\n viewsConfig: resolvedConfig.viewsConfig,\n componentDir: resolvedConfig.componentDir,\n });\n } else {\n throw new Error(\n 'ImageRendererConfig requires either staticRenderer or both viewsConfig and componentDir'\n );\n }\n\n return new ImageRenderer(browser, staticRenderer, resolvedConfig);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/stick/index.ts"],"sourcesContent":["import './allow_cli.cjs';\n// Type-only import — erased at runtime, won't trigger module loading\nimport type { WoodStaticRenderer } from './static_renderer.cjs';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { resolveImageRendererTemplate } from './template_resolver.cjs';\n\nexport type { WoodStaticRenderer };\nexport type {\n WoodStaticRendererConfig,\n WoodRenderOptions,\n WoodRenderToPageOptions,\n WoodRenderResult,\n} from './static_renderer.cjs';\n\n// ─────────────────────────────────────────────────────────────\n// Error Classes\n// ─────────────────────────────────────────────────────────────\n\nexport class PlaywrightNotInstalledError extends Error {\n name = 'PlaywrightNotInstalledError' as const;\n constructor() {\n super(\n 'ImageRenderer requires Playwright. Install it with:\\n' +\n ' npm install playwright\\n' +\n ' npx playwright install chromium'\n );\n }\n}\n\nexport class BrowserLaunchError extends Error {\n name = 'BrowserLaunchError' as const;\n constructor(message: string, public cause?: Error) {\n super(message);\n }\n}\n\nexport class RenderTimeoutError extends Error {\n name = 'RenderTimeoutError' as const;\n constructor(timeoutMs: number) {\n super(`Render timed out after ${timeoutMs}ms`);\n }\n}\n\nexport class RenderError extends Error {\n name = 'RenderError' as const;\n constructor(message: string, public cause?: Error) {\n super(message);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────\n\nexport interface ImageRendererConfig {\n /** Output directory for screenshots */\n outputDir: string;\n /** Default width (default: 1920) */\n width?: number;\n /** Default height (default: 1080) */\n height?: number;\n /** Device scale factor for retina (default: 1) */\n deviceScaleFactor?: number;\n /** Image format (default: 'png') */\n format?: 'png' | 'jpeg';\n /** JPEG quality 0-100 (default: 80) */\n quality?: number;\n /** Wait condition (default: 'networkidle') */\n waitUntil?: 'load' | 'domcontentloaded' | 'networkidle';\n /** Timeout in ms (default: 10000) */\n timeoutMs?: number;\n /** Custom HTML template with {{{HEAD}}}, {{{CSS}}}, {{{APP}}} placeholders */\n template?: string;\n\n // Static renderer config (one of these)\n /** Pre-created WoodStaticRenderer instance */\n staticRenderer?: WoodStaticRenderer;\n /** OR: Path to views.yaml */\n viewsConfig?: string;\n /**\n * Component directory (required if viewsConfig provided).\n * When template is omitted, stick auto-loads <componentDir>/index.html and\n * inlines <componentDir>/styles.css when present.\n */\n componentDir?: string;\n /** Asset path mappings (e.g., { '/images': ['public/images'] }) */\n assets?: Record<string, string[]>;\n}\n\nexport interface CaptureOptions {\n /** View component data */\n view?: any;\n /** Layout data (one object per layout) */\n layout?: any[];\n /** Wood bridge object passed as a prop to layouts and views */\n wood?: any;\n /** Override width */\n width?: number;\n /** Override height */\n height?: number;\n /** Capture full page (default: true) */\n fullPage?: boolean;\n /** Callback executed after page load, before screenshot. Receives the Playwright page object. */\n beforeCapture?: (page: any) => Promise<void>;\n}\n\nexport interface CaptureHtmlOptions {\n /** Override width */\n width?: number;\n /** Override height */\n height?: number;\n /** Capture full page (default: true) */\n fullPage?: boolean;\n /** Callback executed after page load, before screenshot. Receives the Playwright page object. */\n beforeCapture?: (page: any) => Promise<void>;\n}\n\ninterface CaptureResult {\n /** Raw image buffer */\n buffer: Buffer;\n /** Path where image was saved */\n path: string;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Playwright Loader\n// ─────────────────────────────────────────────────────────────\n\ntype PlaywrightModule = typeof import('playwright');\n\nasync function loadPlaywright(): Promise<PlaywrightModule> {\n try {\n const playwright = await import('playwright');\n return playwright;\n } catch {\n throw new PlaywrightNotInstalledError();\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Content Type Helper\n// ─────────────────────────────────────────────────────────────\n\nfunction getContentType(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n const types: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n };\n return types[ext] || 'application/octet-stream';\n}\n\n// ─────────────────────────────────────────────────────────────\n// ImageRenderer Class\n// ─────────────────────────────────────────────────────────────\n\nexport class ImageRenderer {\n private browser: any;\n private staticRenderer: WoodStaticRenderer;\n private config: Required<Omit<ImageRendererConfig, 'staticRenderer' | 'viewsConfig' | 'componentDir' | 'template' | 'assets'>> & {\n outputDir: string;\n template?: string;\n assets?: Record<string, string[]>;\n };\n\n constructor(\n browser: any,\n staticRenderer: WoodStaticRenderer,\n config: ImageRendererConfig\n ) {\n this.browser = browser;\n this.staticRenderer = staticRenderer;\n this.config = {\n outputDir: config.outputDir,\n width: config.width ?? 1920,\n height: config.height ?? 1080,\n deviceScaleFactor: config.deviceScaleFactor ?? 1,\n format: config.format ?? 'png',\n quality: config.quality ?? 80,\n waitUntil: config.waitUntil ?? 'networkidle',\n timeoutMs: config.timeoutMs ?? 10000,\n template: config.template,\n assets: config.assets,\n };\n }\n\n /**\n * Capture a view by dot-path key and save to outputDir\n */\n async capture(\n name: string,\n viewKey: string,\n options?: CaptureOptions\n ): Promise<CaptureResult> {\n const { view, layout, wood } = options ?? {};\n const html = await this.staticRenderer.renderToPage({\n viewKey,\n data: { view, layout },\n wood,\n template: this.config.template,\n });\n\n return this.captureHtmlInternal(name, html, options);\n }\n\n /**\n * Capture raw HTML and save to outputDir\n */\n async captureHtml(\n name: string,\n html: string,\n options?: CaptureHtmlOptions\n ): Promise<CaptureResult> {\n return this.captureHtmlInternal(name, html, options);\n }\n\n /**\n * Internal method to capture HTML to image\n */\n private async captureHtmlInternal(\n name: string,\n html: string,\n options?: CaptureHtmlOptions\n ): Promise<CaptureResult> {\n const width = options?.width ?? this.config.width;\n const height = options?.height ?? this.config.height;\n\n let context: any;\n let page: any;\n\n try {\n context = await this.browser.newContext({\n viewport: { width, height },\n deviceScaleFactor: this.config.deviceScaleFactor,\n });\n\n page = await context.newPage();\n\n // Route Interception Strategy:\n // We use page.goto() with a fake URL instead of page.setContent() because\n // setContent() has no base URL, so relative paths can't resolve.\n const FAKE_BASE_URL = 'http://stick-renderer/';\n\n await page.route(FAKE_BASE_URL, async (route: any) => {\n await route.fulfill({\n body: html,\n contentType: 'text/html',\n });\n });\n\n // Asset route interception\n if (this.config.assets) {\n for (const [urlPath, fsPaths] of Object.entries(this.config.assets)) {\n await page.route(`**${urlPath}/**`, async (route: any) => {\n const url = new URL(route.request().url());\n const relativePath = url.pathname.replace(urlPath, '');\n\n for (const fsPath of fsPaths) {\n const filePath = path.join(fsPath, relativePath);\n try {\n const body = await fs.promises.readFile(filePath);\n const contentType = getContentType(filePath);\n await route.fulfill({ body, contentType });\n return;\n } catch {\n // File not found in this path, try the next one\n }\n }\n\n await route.abort('filenotfound');\n });\n }\n }\n\n const waitUntilMapping = {\n 'load': 'load',\n 'domcontentloaded': 'domcontentloaded',\n 'networkidle': 'networkidle',\n } as const;\n\n try {\n await page.goto(FAKE_BASE_URL, {\n waitUntil: waitUntilMapping[this.config.waitUntil],\n timeout: this.config.timeoutMs,\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('timeout')) {\n throw new RenderTimeoutError(this.config.timeoutMs);\n }\n throw new RenderError(\n 'Failed to render HTML content',\n error instanceof Error ? error : undefined\n );\n }\n\n if (options?.beforeCapture) {\n await options.beforeCapture(page);\n }\n\n const screenshotOptions: {\n type: 'png' | 'jpeg';\n quality?: number;\n fullPage: boolean;\n } = {\n type: this.config.format,\n fullPage: options?.fullPage ?? true,\n };\n\n if (this.config.format === 'jpeg') {\n screenshotOptions.quality = this.config.quality;\n }\n\n const screenshot = await page.screenshot(screenshotOptions);\n const buffer = Buffer.from(screenshot);\n\n const filename = `${name}@${width}x${height}.${this.config.format}`;\n const outputPath = path.join(this.config.outputDir, filename);\n\n await fs.promises.mkdir(this.config.outputDir, { recursive: true });\n await fs.promises.writeFile(outputPath, buffer);\n\n return { buffer, path: outputPath };\n\n } finally {\n if (page) {\n await page.close().catch(() => {});\n }\n if (context) {\n await context.close().catch(() => {});\n }\n }\n }\n\n /**\n * Close browser and clean up resources\n */\n async close(): Promise<void> {\n if (this.browser) {\n await this.browser.close().catch(() => {});\n }\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// Factory Function\n// ─────────────────────────────────────────────────────────────\n\nexport async function createImageRenderer(\n config: ImageRendererConfig\n): Promise<ImageRenderer> {\n const resolvedTemplate = resolveImageRendererTemplate({\n template: config.template,\n componentDir: config.componentDir,\n });\n const resolvedConfig: ImageRendererConfig = {\n ...config,\n template: resolvedTemplate,\n };\n\n const playwright = await loadPlaywright();\n\n let browser: any;\n try {\n browser = await playwright.chromium.launch({\n headless: true,\n });\n } catch (error) {\n throw new BrowserLaunchError(\n 'Failed to launch Chromium. Ensure it is installed with: npx playwright install chromium',\n error instanceof Error ? error : undefined\n );\n }\n\n let staticRenderer: WoodStaticRenderer;\n if (resolvedConfig.staticRenderer) {\n staticRenderer = resolvedConfig.staticRenderer;\n } else if (resolvedConfig.viewsConfig && resolvedConfig.componentDir) {\n const { createWoodStaticRenderer } = await import('./static_renderer.cjs');\n staticRenderer = createWoodStaticRenderer({\n viewsConfig: resolvedConfig.viewsConfig,\n componentDir: resolvedConfig.componentDir,\n });\n } else {\n throw new Error(\n 'ImageRendererConfig requires either staticRenderer or both viewsConfig and componentDir'\n );\n }\n\n return new ImageRenderer(browser, staticRenderer, resolvedConfig);\n}\n"],"mappings":"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","names":[]}
|