@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
|
@@ -38,6 +38,7 @@ class RendererTraceBatchTransport {
|
|
|
38
38
|
this.droppedClosed = 0;
|
|
39
39
|
this.droppedRejected = 0;
|
|
40
40
|
this.droppedRetryExhausted = 0;
|
|
41
|
+
this.identityRestamped = 0;
|
|
41
42
|
this.committedBatches = 0;
|
|
42
43
|
this.retryAttempts = 0;
|
|
43
44
|
this.metadataTruncatedValues = 0;
|
|
@@ -49,8 +50,8 @@ class RendererTraceBatchTransport {
|
|
|
49
50
|
);
|
|
50
51
|
}
|
|
51
52
|
admit(event) {
|
|
52
|
-
const
|
|
53
|
-
|
|
53
|
+
const identity = this.resolveIdentity(event);
|
|
54
|
+
const sequence = identity.sequence;
|
|
54
55
|
if (this.state !== "accepting") {
|
|
55
56
|
this.droppedClosed += 1;
|
|
56
57
|
return { kind: "dropped", sequence, reason: "closed" };
|
|
@@ -60,10 +61,46 @@ class RendererTraceBatchTransport {
|
|
|
60
61
|
this.droppedCapacity += 1;
|
|
61
62
|
return { kind: "dropped", sequence, reason: "capacity" };
|
|
62
63
|
}
|
|
63
|
-
this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence) }));
|
|
64
|
+
this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence, identity) }));
|
|
64
65
|
this.scheduleDrain();
|
|
65
66
|
return { kind: "admitted", sequence };
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolves the queue sequence and preserved identity for an incoming event,
|
|
70
|
+
* reading identity fields from the raw input BEFORE metadata snapshotting so
|
|
71
|
+
* truncation/redaction can never alter identity.
|
|
72
|
+
*
|
|
73
|
+
* A hub-admitted event (valid timestamp + traceSeq) keeps its identity and
|
|
74
|
+
* its queue sequence is derived as traceSeq - 1 so the batch sequence range
|
|
75
|
+
* stays aligned with hub identity. A stamped event whose traceSeq regresses
|
|
76
|
+
* against the already-assigned sequence stream is restamped as legacy (its
|
|
77
|
+
* occurrence timestamp is still preserved, its producerId is dropped so a
|
|
78
|
+
* reassigned sequence cannot masquerade under the durable identity key) and
|
|
79
|
+
* counted in identityRestamped. Legacy events without identity are stamped
|
|
80
|
+
* exactly as before.
|
|
81
|
+
*/
|
|
82
|
+
resolveIdentity(event) {
|
|
83
|
+
const rawTimestamp = typeof event.timestamp === "string" && Number.isFinite(Date.parse(event.timestamp)) ? event.timestamp : void 0;
|
|
84
|
+
const rawSeq = typeof event.traceSeq === "number" && Number.isSafeInteger(event.traceSeq) && event.traceSeq >= 1 ? event.traceSeq : void 0;
|
|
85
|
+
const producerId = typeof event.producerId === "string" && event.producerId.trim().length > 0 ? event.producerId : void 0;
|
|
86
|
+
if (rawTimestamp !== void 0 && rawSeq !== void 0 && rawSeq - 1 >= this.nextSequence) {
|
|
87
|
+
this.nextSequence = rawSeq;
|
|
88
|
+
return {
|
|
89
|
+
sequence: rawSeq - 1,
|
|
90
|
+
timestamp: rawTimestamp,
|
|
91
|
+
...producerId !== void 0 ? { producerId } : {}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (rawTimestamp !== void 0 && rawSeq !== void 0) {
|
|
95
|
+
this.identityRestamped += 1;
|
|
96
|
+
}
|
|
97
|
+
const sequence = this.nextSequence;
|
|
98
|
+
this.nextSequence += 1;
|
|
99
|
+
return {
|
|
100
|
+
sequence,
|
|
101
|
+
...rawTimestamp !== void 0 ? { timestamp: rawTimestamp } : {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
67
104
|
attachPort(port) {
|
|
68
105
|
this.detachPort();
|
|
69
106
|
this.port = port;
|
|
@@ -86,6 +123,7 @@ class RendererTraceBatchTransport {
|
|
|
86
123
|
droppedClosed: this.droppedClosed,
|
|
87
124
|
droppedRejected: this.droppedRejected,
|
|
88
125
|
droppedRetryExhausted: this.droppedRetryExhausted,
|
|
126
|
+
identityRestamped: this.identityRestamped,
|
|
89
127
|
metadataTruncatedValues: this.metadataTruncatedValues,
|
|
90
128
|
metadataRedactedValues: this.metadataRedactedValues,
|
|
91
129
|
metadataSerializationFailures: this.metadataSerializationFailures,
|
|
@@ -252,14 +290,17 @@ class RendererTraceBatchTransport {
|
|
|
252
290
|
this.handleAcknowledgementTimeout(current.batch.batchId, attempt);
|
|
253
291
|
});
|
|
254
292
|
}
|
|
255
|
-
snapshotEvent(event, sequence) {
|
|
293
|
+
snapshotEvent(event, sequence, identity) {
|
|
256
294
|
const snapshot = this.metadataSnapshotter.snapshot(event);
|
|
257
295
|
this.metadataTruncatedValues += snapshot.stats.truncatedValues;
|
|
258
296
|
this.metadataRedactedValues += snapshot.stats.redactedValues;
|
|
259
297
|
this.metadataSerializationFailures += snapshot.stats.serializationFailures;
|
|
260
298
|
const input = snapshot.metadata;
|
|
261
|
-
|
|
262
|
-
|
|
299
|
+
let timestamp = identity.timestamp;
|
|
300
|
+
if (timestamp === void 0) {
|
|
301
|
+
const occurredAt = new Date(this.options.now());
|
|
302
|
+
timestamp = Number.isNaN(occurredAt.getTime()) ? (/* @__PURE__ */ new Date(0)).toISOString() : occurredAt.toISOString();
|
|
303
|
+
}
|
|
263
304
|
return Object.freeze({
|
|
264
305
|
source: this.snapshotString(input.source, "unknown"),
|
|
265
306
|
type: this.snapshotString(input.type, "unknown"),
|
|
@@ -267,6 +308,7 @@ class RendererTraceBatchTransport {
|
|
|
267
308
|
process: "renderer",
|
|
268
309
|
timestamp,
|
|
269
310
|
traceSeq: sequence + 1,
|
|
311
|
+
...identity.producerId !== void 0 ? { producerId: identity.producerId } : {},
|
|
270
312
|
...this.snapshotOptionalString("message", input.message),
|
|
271
313
|
...this.snapshotConversationId(input.conversationId),
|
|
272
314
|
...this.snapshotPayload(input.payload),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tracing/renderer_trace_batch_transport.ts"],"sourcesContent":["import {\n BoundedMetadataSnapshotter,\n DEFAULT_METADATA_SNAPSHOT_LIMITS,\n type TelemetryJsonObject,\n type TelemetryJsonValue,\n} from '@noego/telemetry/core';\nimport { WoodTraceBatchContract } from './wood_trace_batch_contract.js';\nimport type {\n WoodRendererTraceEvent,\n WoodRendererTraceInput,\n WoodTraceBatch,\n WoodTraceBatchAdmissionResult,\n WoodTraceBatchPort,\n WoodTraceBatchTransportOptions,\n WoodTraceBatchTransportStatus,\n} from './types/wood_trace_batch.types.js';\n\ntype QueuedTraceEvent = Readonly<{\n sequence: number;\n event: WoodRendererTraceEvent;\n}>;\n\ntype InFlightTraceBatch = {\n batch: WoodTraceBatch;\n attempts: number;\n awaitingAcknowledgement: boolean;\n retryReady: boolean;\n retryGeneration: number;\n};\n\nexport class RendererTraceBatchTransport {\n private readonly contract = new WoodTraceBatchContract();\n private readonly metadataSnapshotter: BoundedMetadataSnapshotter;\n private readonly queue: QueuedTraceEvent[] = [];\n private state: 'accepting' | 'draining' | 'stopped' = 'accepting';\n private port: WoodTraceBatchPort | null = null;\n private unsubscribePort: (() => void) | null = null;\n private inFlight: InFlightTraceBatch | null = null;\n private nextSequence = 0;\n private drainScheduled = false;\n private droppedCapacity = 0;\n private droppedClosed = 0;\n private droppedRejected = 0;\n private droppedRetryExhausted = 0;\n private committedBatches = 0;\n private retryAttempts = 0;\n private metadataTruncatedValues = 0;\n private metadataRedactedValues = 0;\n private metadataSerializationFailures = 0;\n\n constructor(private readonly options: WoodTraceBatchTransportOptions) {\n this.validateOptions();\n this.metadataSnapshotter = new BoundedMetadataSnapshotter(\n options.metadataSnapshotLimits ?? DEFAULT_METADATA_SNAPSHOT_LIMITS,\n );\n }\n\n admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult {\n const sequence = this.nextSequence;\n this.nextSequence += 1;\n if (this.state !== 'accepting') {\n this.droppedClosed += 1;\n return { kind: 'dropped', sequence, reason: 'closed' };\n }\n\n const retainedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n if (retainedEvents >= this.options.maxQueuedEvents) {\n this.droppedCapacity += 1;\n return { kind: 'dropped', sequence, reason: 'capacity' };\n }\n\n this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence) }));\n this.scheduleDrain();\n return { kind: 'admitted', sequence };\n }\n\n attachPort(port: WoodTraceBatchPort): void {\n this.detachPort();\n this.port = port;\n this.unsubscribePort = port.subscribe((message) => this.handleAcknowledgement(message));\n if (this.inFlight) {\n this.inFlight.awaitingAcknowledgement = false;\n this.inFlight.retryReady = true;\n this.inFlight.retryGeneration += 1;\n }\n this.scheduleDrain();\n }\n\n status(): WoodTraceBatchTransportStatus {\n return Object.freeze({\n state: this.state,\n producerId: this.options.producerId,\n nextSequence: this.nextSequence,\n queuedEvents: this.queue.length,\n inFlightBatchId: this.inFlight?.batch.batchId ?? null,\n droppedCapacity: this.droppedCapacity,\n droppedClosed: this.droppedClosed,\n droppedRejected: this.droppedRejected,\n droppedRetryExhausted: this.droppedRetryExhausted,\n metadataTruncatedValues: this.metadataTruncatedValues,\n metadataRedactedValues: this.metadataRedactedValues,\n metadataSerializationFailures: this.metadataSerializationFailures,\n committedBatches: this.committedBatches,\n retryAttempts: this.retryAttempts,\n });\n }\n\n async flush(deadlineMs: number): Promise<void> {\n this.scheduleDrain();\n while (this.hasPendingEvents() && this.options.now() < deadlineMs) {\n await this.options.delay(1);\n this.scheduleDrain();\n }\n }\n\n async close(deadlineMs: number): Promise<void> {\n if (this.state === 'stopped') {\n return;\n }\n this.state = 'draining';\n await this.flush(deadlineMs);\n const abandonedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n this.droppedClosed += abandonedEvents;\n this.queue.length = 0;\n this.inFlight = null;\n this.detachPort();\n this.state = 'stopped';\n }\n\n private abandonRetryExhausted(): void {\n if (!this.inFlight) {\n return;\n }\n this.droppedRetryExhausted += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n }\n\n private createInFlightBatch(): void {\n if (this.inFlight || this.queue.length === 0 || !this.port) {\n return;\n }\n const entries = this.queue.splice(0, this.options.maxBatchEvents);\n const first = entries[0];\n if (!first) {\n return;\n }\n this.inFlight = {\n batch: this.contract.create(\n this.options.producerId,\n first.sequence,\n entries.map((entry) => entry.event),\n ),\n attempts: 0,\n awaitingAcknowledgement: false,\n retryReady: true,\n retryGeneration: 0,\n };\n }\n\n private detachPort(): void {\n this.unsubscribePort?.();\n this.unsubscribePort = null;\n this.port?.close();\n this.port = null;\n }\n\n private drain(): void {\n this.createInFlightBatch();\n this.sendInFlightBatch();\n }\n\n private handleAcknowledgement(message: unknown): void {\n const parsed = this.contract.parseAcknowledgement(message);\n if (!parsed.ok || !this.inFlight) {\n return;\n }\n const acknowledgement = parsed.acknowledgement;\n if (acknowledgement.batchId !== this.inFlight.batch.batchId) {\n return;\n }\n\n this.inFlight.retryGeneration += 1;\n this.inFlight.awaitingAcknowledgement = false;\n if (acknowledgement.kind === 'committed') {\n if (acknowledgement.acceptedEvents !== this.inFlight.batch.events.length) {\n this.scheduleRetry(0);\n return;\n }\n this.committedBatches += 1;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n if (acknowledgement.kind === 'rejected') {\n this.droppedRejected += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n this.scheduleRetry(acknowledgement.retryAfterMs);\n }\n\n private handleAcknowledgementTimeout(batchId: string, attempt: number): void {\n if (!this.inFlight\n || this.inFlight.batch.batchId !== batchId\n || this.inFlight.attempts !== attempt\n || !this.inFlight.awaitingAcknowledgement) {\n return;\n }\n this.inFlight.awaitingAcknowledgement = false;\n this.scheduleRetry(this.retryDelay(attempt));\n }\n\n private hasPendingEvents(): boolean {\n return this.queue.length > 0 || this.inFlight !== null;\n }\n\n private retryDelay(attempt: number): number {\n return this.options.retryBaseDelayMs * (2 ** Math.max(0, attempt - 1));\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) {\n return;\n }\n this.drainScheduled = true;\n this.options.schedule(() => {\n this.drainScheduled = false;\n this.drain();\n });\n }\n\n private scheduleRetry(requestedDelayMs: number): void {\n if (!this.inFlight) {\n return;\n }\n if (this.inFlight.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n this.inFlight.retryReady = false;\n const generation = this.inFlight.retryGeneration + 1;\n this.inFlight.retryGeneration = generation;\n const delayMs = Math.max(requestedDelayMs, this.retryDelay(this.inFlight.attempts));\n void this.options.delay(delayMs).then(() => {\n if (!this.inFlight || this.inFlight.retryGeneration !== generation) {\n return;\n }\n this.inFlight.retryReady = true;\n this.scheduleDrain();\n });\n }\n\n private sendInFlightBatch(): void {\n const current = this.inFlight;\n const port = this.port;\n if (!current || !port || current.awaitingAcknowledgement || !current.retryReady) {\n return;\n }\n if (current.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n current.attempts += 1;\n if (current.attempts > 1) {\n this.retryAttempts += 1;\n }\n current.awaitingAcknowledgement = true;\n current.retryReady = false;\n const attempt = current.attempts;\n try {\n port.postMessage(current.batch);\n } catch {\n current.awaitingAcknowledgement = false;\n this.detachPort();\n return;\n }\n\n void this.options.delay(this.options.acknowledgementTimeoutMs).then(() => {\n this.handleAcknowledgementTimeout(current.batch.batchId, attempt);\n });\n }\n\n private snapshotEvent(\n event: WoodRendererTraceInput,\n sequence: number,\n ): WoodRendererTraceEvent {\n const snapshot = this.metadataSnapshotter.snapshot(event);\n this.metadataTruncatedValues += snapshot.stats.truncatedValues;\n this.metadataRedactedValues += snapshot.stats.redactedValues;\n this.metadataSerializationFailures += snapshot.stats.serializationFailures;\n const input = snapshot.metadata;\n const occurredAt = new Date(this.options.now());\n const timestamp = Number.isNaN(occurredAt.getTime())\n ? new Date(0).toISOString()\n : occurredAt.toISOString();\n return Object.freeze({\n source: this.snapshotString(input.source, 'unknown'),\n type: this.snapshotString(input.type, 'unknown'),\n level: this.snapshotString(input.level, 'info'),\n process: 'renderer',\n timestamp,\n traceSeq: sequence + 1,\n ...this.snapshotOptionalString('message', input.message),\n ...this.snapshotConversationId(input.conversationId),\n ...this.snapshotPayload(input.payload),\n ...this.snapshotOptionalString('windowId', input.windowId),\n ...this.snapshotOptionalNumber('webContentsId', input.webContentsId),\n ...this.snapshotOptionalString('routeKey', input.routeKey),\n ...this.snapshotOptionalString('harnessId', input.harnessId),\n });\n }\n\n private snapshotConversationId(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'conversationId'> | Record<string, never> {\n return typeof value === 'string' || typeof value === 'number'\n ? { conversationId: value }\n : {};\n }\n\n private snapshotOptionalNumber<Key extends 'webContentsId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'number' && Number.isFinite(value)\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotOptionalString<Key extends 'message' | 'windowId' | 'routeKey' | 'harnessId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'string'\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotPayload(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'payload'> | Record<string, never> {\n if (value === undefined) {\n return {};\n }\n const payload: TelemetryJsonObject = this.isJsonObject(value)\n ? value\n : Object.freeze({ __telemetry: value });\n return { payload };\n }\n\n private snapshotString(value: TelemetryJsonValue | undefined, fallback: string): string {\n return typeof value === 'string' && value.trim().length > 0 ? value : fallback;\n }\n\n private isJsonObject(value: TelemetryJsonValue): value is TelemetryJsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private validateOptions(): void {\n const validCapacity = Number.isSafeInteger(this.options.maxQueuedEvents)\n && this.options.maxQueuedEvents > 0\n && Number.isSafeInteger(this.options.maxBatchEvents)\n && this.options.maxBatchEvents > 0\n && this.options.maxBatchEvents <= this.options.maxQueuedEvents;\n const validRetry = Number.isSafeInteger(this.options.retryLimit)\n && this.options.retryLimit >= 0\n && Number.isFinite(this.options.retryBaseDelayMs)\n && this.options.retryBaseDelayMs >= 0\n && Number.isFinite(this.options.acknowledgementTimeoutMs)\n && this.options.acknowledgementTimeoutMs > 0;\n if (!this.options.producerId.trim() || !validCapacity || !validRetry) {\n throw new Error('Renderer trace batch transport options are invalid');\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/tracing/renderer_trace_batch_transport.ts"],"sourcesContent":["import {\n BoundedMetadataSnapshotter,\n DEFAULT_METADATA_SNAPSHOT_LIMITS,\n type TelemetryJsonObject,\n type TelemetryJsonValue,\n} from '@noego/telemetry/core';\nimport { WoodTraceBatchContract } from './wood_trace_batch_contract.js';\nimport type {\n WoodRendererTraceEvent,\n WoodRendererTraceInput,\n WoodTraceBatch,\n WoodTraceBatchAdmissionResult,\n WoodTraceBatchPort,\n WoodTraceBatchTransportOptions,\n WoodTraceBatchTransportStatus,\n} from './types/wood_trace_batch.types.js';\n\ntype QueuedTraceEvent = Readonly<{\n sequence: number;\n event: WoodRendererTraceEvent;\n}>;\n\ntype InFlightTraceBatch = {\n batch: WoodTraceBatch;\n attempts: number;\n awaitingAcknowledgement: boolean;\n retryReady: boolean;\n retryGeneration: number;\n};\n\nexport class RendererTraceBatchTransport {\n private readonly contract = new WoodTraceBatchContract();\n private readonly metadataSnapshotter: BoundedMetadataSnapshotter;\n private readonly queue: QueuedTraceEvent[] = [];\n private state: 'accepting' | 'draining' | 'stopped' = 'accepting';\n private port: WoodTraceBatchPort | null = null;\n private unsubscribePort: (() => void) | null = null;\n private inFlight: InFlightTraceBatch | null = null;\n private nextSequence = 0;\n private drainScheduled = false;\n private droppedCapacity = 0;\n private droppedClosed = 0;\n private droppedRejected = 0;\n private droppedRetryExhausted = 0;\n private identityRestamped = 0;\n private committedBatches = 0;\n private retryAttempts = 0;\n private metadataTruncatedValues = 0;\n private metadataRedactedValues = 0;\n private metadataSerializationFailures = 0;\n\n constructor(private readonly options: WoodTraceBatchTransportOptions) {\n this.validateOptions();\n this.metadataSnapshotter = new BoundedMetadataSnapshotter(\n options.metadataSnapshotLimits ?? DEFAULT_METADATA_SNAPSHOT_LIMITS,\n );\n }\n\n admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult {\n const identity = this.resolveIdentity(event);\n const sequence = identity.sequence;\n if (this.state !== 'accepting') {\n this.droppedClosed += 1;\n return { kind: 'dropped', sequence, reason: 'closed' };\n }\n\n const retainedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n if (retainedEvents >= this.options.maxQueuedEvents) {\n this.droppedCapacity += 1;\n return { kind: 'dropped', sequence, reason: 'capacity' };\n }\n\n this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence, identity) }));\n this.scheduleDrain();\n return { kind: 'admitted', sequence };\n }\n\n /**\n * Resolves the queue sequence and preserved identity for an incoming event,\n * reading identity fields from the raw input BEFORE metadata snapshotting so\n * truncation/redaction can never alter identity.\n *\n * A hub-admitted event (valid timestamp + traceSeq) keeps its identity and\n * its queue sequence is derived as traceSeq - 1 so the batch sequence range\n * stays aligned with hub identity. A stamped event whose traceSeq regresses\n * against the already-assigned sequence stream is restamped as legacy (its\n * occurrence timestamp is still preserved, its producerId is dropped so a\n * reassigned sequence cannot masquerade under the durable identity key) and\n * counted in identityRestamped. Legacy events without identity are stamped\n * exactly as before.\n */\n private resolveIdentity(event: WoodRendererTraceInput): {\n sequence: number;\n timestamp?: string;\n producerId?: string;\n } {\n const rawTimestamp = typeof event.timestamp === 'string'\n && Number.isFinite(Date.parse(event.timestamp))\n ? event.timestamp\n : undefined;\n const rawSeq = typeof event.traceSeq === 'number'\n && Number.isSafeInteger(event.traceSeq)\n && event.traceSeq >= 1\n ? event.traceSeq\n : undefined;\n const producerId = typeof event.producerId === 'string' && event.producerId.trim().length > 0\n ? event.producerId\n : undefined;\n\n if (rawTimestamp !== undefined && rawSeq !== undefined && rawSeq - 1 >= this.nextSequence) {\n this.nextSequence = rawSeq;\n return {\n sequence: rawSeq - 1,\n timestamp: rawTimestamp,\n ...(producerId !== undefined ? { producerId } : {}),\n };\n }\n\n if (rawTimestamp !== undefined && rawSeq !== undefined) {\n // Stamped but non-monotonic against this transport's sequence stream:\n // protocol survival wins, durable sequence identity is sacrificed loudly.\n this.identityRestamped += 1;\n }\n\n const sequence = this.nextSequence;\n this.nextSequence += 1;\n return {\n sequence,\n ...(rawTimestamp !== undefined ? { timestamp: rawTimestamp } : {}),\n };\n }\n\n attachPort(port: WoodTraceBatchPort): void {\n this.detachPort();\n this.port = port;\n this.unsubscribePort = port.subscribe((message) => this.handleAcknowledgement(message));\n if (this.inFlight) {\n this.inFlight.awaitingAcknowledgement = false;\n this.inFlight.retryReady = true;\n this.inFlight.retryGeneration += 1;\n }\n this.scheduleDrain();\n }\n\n status(): WoodTraceBatchTransportStatus {\n return Object.freeze({\n state: this.state,\n producerId: this.options.producerId,\n nextSequence: this.nextSequence,\n queuedEvents: this.queue.length,\n inFlightBatchId: this.inFlight?.batch.batchId ?? null,\n droppedCapacity: this.droppedCapacity,\n droppedClosed: this.droppedClosed,\n droppedRejected: this.droppedRejected,\n droppedRetryExhausted: this.droppedRetryExhausted,\n identityRestamped: this.identityRestamped,\n metadataTruncatedValues: this.metadataTruncatedValues,\n metadataRedactedValues: this.metadataRedactedValues,\n metadataSerializationFailures: this.metadataSerializationFailures,\n committedBatches: this.committedBatches,\n retryAttempts: this.retryAttempts,\n });\n }\n\n async flush(deadlineMs: number): Promise<void> {\n this.scheduleDrain();\n while (this.hasPendingEvents() && this.options.now() < deadlineMs) {\n await this.options.delay(1);\n this.scheduleDrain();\n }\n }\n\n async close(deadlineMs: number): Promise<void> {\n if (this.state === 'stopped') {\n return;\n }\n this.state = 'draining';\n await this.flush(deadlineMs);\n const abandonedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n this.droppedClosed += abandonedEvents;\n this.queue.length = 0;\n this.inFlight = null;\n this.detachPort();\n this.state = 'stopped';\n }\n\n private abandonRetryExhausted(): void {\n if (!this.inFlight) {\n return;\n }\n this.droppedRetryExhausted += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n }\n\n private createInFlightBatch(): void {\n if (this.inFlight || this.queue.length === 0 || !this.port) {\n return;\n }\n const entries = this.queue.splice(0, this.options.maxBatchEvents);\n const first = entries[0];\n if (!first) {\n return;\n }\n this.inFlight = {\n batch: this.contract.create(\n this.options.producerId,\n first.sequence,\n entries.map((entry) => entry.event),\n ),\n attempts: 0,\n awaitingAcknowledgement: false,\n retryReady: true,\n retryGeneration: 0,\n };\n }\n\n private detachPort(): void {\n this.unsubscribePort?.();\n this.unsubscribePort = null;\n this.port?.close();\n this.port = null;\n }\n\n private drain(): void {\n this.createInFlightBatch();\n this.sendInFlightBatch();\n }\n\n private handleAcknowledgement(message: unknown): void {\n const parsed = this.contract.parseAcknowledgement(message);\n if (!parsed.ok || !this.inFlight) {\n return;\n }\n const acknowledgement = parsed.acknowledgement;\n if (acknowledgement.batchId !== this.inFlight.batch.batchId) {\n return;\n }\n\n this.inFlight.retryGeneration += 1;\n this.inFlight.awaitingAcknowledgement = false;\n if (acknowledgement.kind === 'committed') {\n if (acknowledgement.acceptedEvents !== this.inFlight.batch.events.length) {\n this.scheduleRetry(0);\n return;\n }\n this.committedBatches += 1;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n if (acknowledgement.kind === 'rejected') {\n this.droppedRejected += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n this.scheduleRetry(acknowledgement.retryAfterMs);\n }\n\n private handleAcknowledgementTimeout(batchId: string, attempt: number): void {\n if (!this.inFlight\n || this.inFlight.batch.batchId !== batchId\n || this.inFlight.attempts !== attempt\n || !this.inFlight.awaitingAcknowledgement) {\n return;\n }\n this.inFlight.awaitingAcknowledgement = false;\n this.scheduleRetry(this.retryDelay(attempt));\n }\n\n private hasPendingEvents(): boolean {\n return this.queue.length > 0 || this.inFlight !== null;\n }\n\n private retryDelay(attempt: number): number {\n return this.options.retryBaseDelayMs * (2 ** Math.max(0, attempt - 1));\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) {\n return;\n }\n this.drainScheduled = true;\n this.options.schedule(() => {\n this.drainScheduled = false;\n this.drain();\n });\n }\n\n private scheduleRetry(requestedDelayMs: number): void {\n if (!this.inFlight) {\n return;\n }\n if (this.inFlight.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n this.inFlight.retryReady = false;\n const generation = this.inFlight.retryGeneration + 1;\n this.inFlight.retryGeneration = generation;\n const delayMs = Math.max(requestedDelayMs, this.retryDelay(this.inFlight.attempts));\n void this.options.delay(delayMs).then(() => {\n if (!this.inFlight || this.inFlight.retryGeneration !== generation) {\n return;\n }\n this.inFlight.retryReady = true;\n this.scheduleDrain();\n });\n }\n\n private sendInFlightBatch(): void {\n const current = this.inFlight;\n const port = this.port;\n if (!current || !port || current.awaitingAcknowledgement || !current.retryReady) {\n return;\n }\n if (current.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n current.attempts += 1;\n if (current.attempts > 1) {\n this.retryAttempts += 1;\n }\n current.awaitingAcknowledgement = true;\n current.retryReady = false;\n const attempt = current.attempts;\n try {\n port.postMessage(current.batch);\n } catch {\n current.awaitingAcknowledgement = false;\n this.detachPort();\n return;\n }\n\n void this.options.delay(this.options.acknowledgementTimeoutMs).then(() => {\n this.handleAcknowledgementTimeout(current.batch.batchId, attempt);\n });\n }\n\n private snapshotEvent(\n event: WoodRendererTraceInput,\n sequence: number,\n identity: { timestamp?: string; producerId?: string },\n ): WoodRendererTraceEvent {\n const snapshot = this.metadataSnapshotter.snapshot(event);\n this.metadataTruncatedValues += snapshot.stats.truncatedValues;\n this.metadataRedactedValues += snapshot.stats.redactedValues;\n this.metadataSerializationFailures += snapshot.stats.serializationFailures;\n const input = snapshot.metadata;\n // A hub-preserved occurrence timestamp is authoritative; only legacy\n // unstamped events receive a transport-stamped time.\n let timestamp = identity.timestamp;\n if (timestamp === undefined) {\n const occurredAt = new Date(this.options.now());\n timestamp = Number.isNaN(occurredAt.getTime())\n ? new Date(0).toISOString()\n : occurredAt.toISOString();\n }\n return Object.freeze({\n source: this.snapshotString(input.source, 'unknown'),\n type: this.snapshotString(input.type, 'unknown'),\n level: this.snapshotString(input.level, 'info'),\n process: 'renderer',\n timestamp,\n traceSeq: sequence + 1,\n ...(identity.producerId !== undefined ? { producerId: identity.producerId } : {}),\n ...this.snapshotOptionalString('message', input.message),\n ...this.snapshotConversationId(input.conversationId),\n ...this.snapshotPayload(input.payload),\n ...this.snapshotOptionalString('windowId', input.windowId),\n ...this.snapshotOptionalNumber('webContentsId', input.webContentsId),\n ...this.snapshotOptionalString('routeKey', input.routeKey),\n ...this.snapshotOptionalString('harnessId', input.harnessId),\n });\n }\n\n private snapshotConversationId(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'conversationId'> | Record<string, never> {\n return typeof value === 'string' || typeof value === 'number'\n ? { conversationId: value }\n : {};\n }\n\n private snapshotOptionalNumber<Key extends 'webContentsId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'number' && Number.isFinite(value)\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotOptionalString<Key extends 'message' | 'windowId' | 'routeKey' | 'harnessId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'string'\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotPayload(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'payload'> | Record<string, never> {\n if (value === undefined) {\n return {};\n }\n const payload: TelemetryJsonObject = this.isJsonObject(value)\n ? value\n : Object.freeze({ __telemetry: value });\n return { payload };\n }\n\n private snapshotString(value: TelemetryJsonValue | undefined, fallback: string): string {\n return typeof value === 'string' && value.trim().length > 0 ? value : fallback;\n }\n\n private isJsonObject(value: TelemetryJsonValue): value is TelemetryJsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private validateOptions(): void {\n const validCapacity = Number.isSafeInteger(this.options.maxQueuedEvents)\n && this.options.maxQueuedEvents > 0\n && Number.isSafeInteger(this.options.maxBatchEvents)\n && this.options.maxBatchEvents > 0\n && this.options.maxBatchEvents <= this.options.maxQueuedEvents;\n const validRetry = Number.isSafeInteger(this.options.retryLimit)\n && this.options.retryLimit >= 0\n && Number.isFinite(this.options.retryBaseDelayMs)\n && this.options.retryBaseDelayMs >= 0\n && Number.isFinite(this.options.acknowledgementTimeoutMs)\n && this.options.acknowledgementTimeoutMs > 0;\n if (!this.options.producerId.trim() || !validCapacity || !validRetry) {\n throw new Error('Renderer trace batch transport options are invalid');\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WoodTraceBatchTransportOptions, WoodRendererTraceInput, WoodTraceBatchAdmissionResult, WoodTraceBatchPort, WoodTraceBatchTransportStatus } from './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 class RendererTraceBatchTransport {
|
|
@@ -18,6 +18,7 @@ declare class RendererTraceBatchTransport {
|
|
|
18
18
|
private droppedClosed;
|
|
19
19
|
private droppedRejected;
|
|
20
20
|
private droppedRetryExhausted;
|
|
21
|
+
private identityRestamped;
|
|
21
22
|
private committedBatches;
|
|
22
23
|
private retryAttempts;
|
|
23
24
|
private metadataTruncatedValues;
|
|
@@ -25,6 +26,21 @@ declare class RendererTraceBatchTransport {
|
|
|
25
26
|
private metadataSerializationFailures;
|
|
26
27
|
constructor(options: WoodTraceBatchTransportOptions);
|
|
27
28
|
admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult;
|
|
29
|
+
/**
|
|
30
|
+
* Resolves the queue sequence and preserved identity for an incoming event,
|
|
31
|
+
* reading identity fields from the raw input BEFORE metadata snapshotting so
|
|
32
|
+
* truncation/redaction can never alter identity.
|
|
33
|
+
*
|
|
34
|
+
* A hub-admitted event (valid timestamp + traceSeq) keeps its identity and
|
|
35
|
+
* its queue sequence is derived as traceSeq - 1 so the batch sequence range
|
|
36
|
+
* stays aligned with hub identity. A stamped event whose traceSeq regresses
|
|
37
|
+
* against the already-assigned sequence stream is restamped as legacy (its
|
|
38
|
+
* occurrence timestamp is still preserved, its producerId is dropped so a
|
|
39
|
+
* reassigned sequence cannot masquerade under the durable identity key) and
|
|
40
|
+
* counted in identityRestamped. Legacy events without identity are stamped
|
|
41
|
+
* exactly as before.
|
|
42
|
+
*/
|
|
43
|
+
private resolveIdentity;
|
|
28
44
|
attachPort(port: WoodTraceBatchPort): void;
|
|
29
45
|
status(): WoodTraceBatchTransportStatus;
|
|
30
46
|
flush(deadlineMs: number): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WoodTraceBatchTransportOptions, WoodRendererTraceInput, WoodTraceBatchAdmissionResult, WoodTraceBatchPort, WoodTraceBatchTransportStatus } from './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 class RendererTraceBatchTransport {
|
|
@@ -18,6 +18,7 @@ declare class RendererTraceBatchTransport {
|
|
|
18
18
|
private droppedClosed;
|
|
19
19
|
private droppedRejected;
|
|
20
20
|
private droppedRetryExhausted;
|
|
21
|
+
private identityRestamped;
|
|
21
22
|
private committedBatches;
|
|
22
23
|
private retryAttempts;
|
|
23
24
|
private metadataTruncatedValues;
|
|
@@ -25,6 +26,21 @@ declare class RendererTraceBatchTransport {
|
|
|
25
26
|
private metadataSerializationFailures;
|
|
26
27
|
constructor(options: WoodTraceBatchTransportOptions);
|
|
27
28
|
admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult;
|
|
29
|
+
/**
|
|
30
|
+
* Resolves the queue sequence and preserved identity for an incoming event,
|
|
31
|
+
* reading identity fields from the raw input BEFORE metadata snapshotting so
|
|
32
|
+
* truncation/redaction can never alter identity.
|
|
33
|
+
*
|
|
34
|
+
* A hub-admitted event (valid timestamp + traceSeq) keeps its identity and
|
|
35
|
+
* its queue sequence is derived as traceSeq - 1 so the batch sequence range
|
|
36
|
+
* stays aligned with hub identity. A stamped event whose traceSeq regresses
|
|
37
|
+
* against the already-assigned sequence stream is restamped as legacy (its
|
|
38
|
+
* occurrence timestamp is still preserved, its producerId is dropped so a
|
|
39
|
+
* reassigned sequence cannot masquerade under the durable identity key) and
|
|
40
|
+
* counted in identityRestamped. Legacy events without identity are stamped
|
|
41
|
+
* exactly as before.
|
|
42
|
+
*/
|
|
43
|
+
private resolveIdentity;
|
|
28
44
|
attachPort(port: WoodTraceBatchPort): void;
|
|
29
45
|
status(): WoodTraceBatchTransportStatus;
|
|
30
46
|
flush(deadlineMs: number): Promise<void>;
|
|
@@ -18,6 +18,7 @@ class RendererTraceBatchTransport {
|
|
|
18
18
|
this.droppedClosed = 0;
|
|
19
19
|
this.droppedRejected = 0;
|
|
20
20
|
this.droppedRetryExhausted = 0;
|
|
21
|
+
this.identityRestamped = 0;
|
|
21
22
|
this.committedBatches = 0;
|
|
22
23
|
this.retryAttempts = 0;
|
|
23
24
|
this.metadataTruncatedValues = 0;
|
|
@@ -29,8 +30,8 @@ class RendererTraceBatchTransport {
|
|
|
29
30
|
);
|
|
30
31
|
}
|
|
31
32
|
admit(event) {
|
|
32
|
-
const
|
|
33
|
-
|
|
33
|
+
const identity = this.resolveIdentity(event);
|
|
34
|
+
const sequence = identity.sequence;
|
|
34
35
|
if (this.state !== "accepting") {
|
|
35
36
|
this.droppedClosed += 1;
|
|
36
37
|
return { kind: "dropped", sequence, reason: "closed" };
|
|
@@ -40,10 +41,46 @@ class RendererTraceBatchTransport {
|
|
|
40
41
|
this.droppedCapacity += 1;
|
|
41
42
|
return { kind: "dropped", sequence, reason: "capacity" };
|
|
42
43
|
}
|
|
43
|
-
this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence) }));
|
|
44
|
+
this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence, identity) }));
|
|
44
45
|
this.scheduleDrain();
|
|
45
46
|
return { kind: "admitted", sequence };
|
|
46
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves the queue sequence and preserved identity for an incoming event,
|
|
50
|
+
* reading identity fields from the raw input BEFORE metadata snapshotting so
|
|
51
|
+
* truncation/redaction can never alter identity.
|
|
52
|
+
*
|
|
53
|
+
* A hub-admitted event (valid timestamp + traceSeq) keeps its identity and
|
|
54
|
+
* its queue sequence is derived as traceSeq - 1 so the batch sequence range
|
|
55
|
+
* stays aligned with hub identity. A stamped event whose traceSeq regresses
|
|
56
|
+
* against the already-assigned sequence stream is restamped as legacy (its
|
|
57
|
+
* occurrence timestamp is still preserved, its producerId is dropped so a
|
|
58
|
+
* reassigned sequence cannot masquerade under the durable identity key) and
|
|
59
|
+
* counted in identityRestamped. Legacy events without identity are stamped
|
|
60
|
+
* exactly as before.
|
|
61
|
+
*/
|
|
62
|
+
resolveIdentity(event) {
|
|
63
|
+
const rawTimestamp = typeof event.timestamp === "string" && Number.isFinite(Date.parse(event.timestamp)) ? event.timestamp : void 0;
|
|
64
|
+
const rawSeq = typeof event.traceSeq === "number" && Number.isSafeInteger(event.traceSeq) && event.traceSeq >= 1 ? event.traceSeq : void 0;
|
|
65
|
+
const producerId = typeof event.producerId === "string" && event.producerId.trim().length > 0 ? event.producerId : void 0;
|
|
66
|
+
if (rawTimestamp !== void 0 && rawSeq !== void 0 && rawSeq - 1 >= this.nextSequence) {
|
|
67
|
+
this.nextSequence = rawSeq;
|
|
68
|
+
return {
|
|
69
|
+
sequence: rawSeq - 1,
|
|
70
|
+
timestamp: rawTimestamp,
|
|
71
|
+
...producerId !== void 0 ? { producerId } : {}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (rawTimestamp !== void 0 && rawSeq !== void 0) {
|
|
75
|
+
this.identityRestamped += 1;
|
|
76
|
+
}
|
|
77
|
+
const sequence = this.nextSequence;
|
|
78
|
+
this.nextSequence += 1;
|
|
79
|
+
return {
|
|
80
|
+
sequence,
|
|
81
|
+
...rawTimestamp !== void 0 ? { timestamp: rawTimestamp } : {}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
47
84
|
attachPort(port) {
|
|
48
85
|
this.detachPort();
|
|
49
86
|
this.port = port;
|
|
@@ -66,6 +103,7 @@ class RendererTraceBatchTransport {
|
|
|
66
103
|
droppedClosed: this.droppedClosed,
|
|
67
104
|
droppedRejected: this.droppedRejected,
|
|
68
105
|
droppedRetryExhausted: this.droppedRetryExhausted,
|
|
106
|
+
identityRestamped: this.identityRestamped,
|
|
69
107
|
metadataTruncatedValues: this.metadataTruncatedValues,
|
|
70
108
|
metadataRedactedValues: this.metadataRedactedValues,
|
|
71
109
|
metadataSerializationFailures: this.metadataSerializationFailures,
|
|
@@ -232,14 +270,17 @@ class RendererTraceBatchTransport {
|
|
|
232
270
|
this.handleAcknowledgementTimeout(current.batch.batchId, attempt);
|
|
233
271
|
});
|
|
234
272
|
}
|
|
235
|
-
snapshotEvent(event, sequence) {
|
|
273
|
+
snapshotEvent(event, sequence, identity) {
|
|
236
274
|
const snapshot = this.metadataSnapshotter.snapshot(event);
|
|
237
275
|
this.metadataTruncatedValues += snapshot.stats.truncatedValues;
|
|
238
276
|
this.metadataRedactedValues += snapshot.stats.redactedValues;
|
|
239
277
|
this.metadataSerializationFailures += snapshot.stats.serializationFailures;
|
|
240
278
|
const input = snapshot.metadata;
|
|
241
|
-
|
|
242
|
-
|
|
279
|
+
let timestamp = identity.timestamp;
|
|
280
|
+
if (timestamp === void 0) {
|
|
281
|
+
const occurredAt = new Date(this.options.now());
|
|
282
|
+
timestamp = Number.isNaN(occurredAt.getTime()) ? (/* @__PURE__ */ new Date(0)).toISOString() : occurredAt.toISOString();
|
|
283
|
+
}
|
|
243
284
|
return Object.freeze({
|
|
244
285
|
source: this.snapshotString(input.source, "unknown"),
|
|
245
286
|
type: this.snapshotString(input.type, "unknown"),
|
|
@@ -247,6 +288,7 @@ class RendererTraceBatchTransport {
|
|
|
247
288
|
process: "renderer",
|
|
248
289
|
timestamp,
|
|
249
290
|
traceSeq: sequence + 1,
|
|
291
|
+
...identity.producerId !== void 0 ? { producerId: identity.producerId } : {},
|
|
250
292
|
...this.snapshotOptionalString("message", input.message),
|
|
251
293
|
...this.snapshotConversationId(input.conversationId),
|
|
252
294
|
...this.snapshotPayload(input.payload),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tracing/renderer_trace_batch_transport.ts"],"sourcesContent":["import {\n BoundedMetadataSnapshotter,\n DEFAULT_METADATA_SNAPSHOT_LIMITS,\n type TelemetryJsonObject,\n type TelemetryJsonValue,\n} from '@noego/telemetry/core';\nimport { WoodTraceBatchContract } from './wood_trace_batch_contract.js';\nimport type {\n WoodRendererTraceEvent,\n WoodRendererTraceInput,\n WoodTraceBatch,\n WoodTraceBatchAdmissionResult,\n WoodTraceBatchPort,\n WoodTraceBatchTransportOptions,\n WoodTraceBatchTransportStatus,\n} from './types/wood_trace_batch.types.js';\n\ntype QueuedTraceEvent = Readonly<{\n sequence: number;\n event: WoodRendererTraceEvent;\n}>;\n\ntype InFlightTraceBatch = {\n batch: WoodTraceBatch;\n attempts: number;\n awaitingAcknowledgement: boolean;\n retryReady: boolean;\n retryGeneration: number;\n};\n\nexport class RendererTraceBatchTransport {\n private readonly contract = new WoodTraceBatchContract();\n private readonly metadataSnapshotter: BoundedMetadataSnapshotter;\n private readonly queue: QueuedTraceEvent[] = [];\n private state: 'accepting' | 'draining' | 'stopped' = 'accepting';\n private port: WoodTraceBatchPort | null = null;\n private unsubscribePort: (() => void) | null = null;\n private inFlight: InFlightTraceBatch | null = null;\n private nextSequence = 0;\n private drainScheduled = false;\n private droppedCapacity = 0;\n private droppedClosed = 0;\n private droppedRejected = 0;\n private droppedRetryExhausted = 0;\n private committedBatches = 0;\n private retryAttempts = 0;\n private metadataTruncatedValues = 0;\n private metadataRedactedValues = 0;\n private metadataSerializationFailures = 0;\n\n constructor(private readonly options: WoodTraceBatchTransportOptions) {\n this.validateOptions();\n this.metadataSnapshotter = new BoundedMetadataSnapshotter(\n options.metadataSnapshotLimits ?? DEFAULT_METADATA_SNAPSHOT_LIMITS,\n );\n }\n\n admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult {\n const sequence = this.nextSequence;\n this.nextSequence += 1;\n if (this.state !== 'accepting') {\n this.droppedClosed += 1;\n return { kind: 'dropped', sequence, reason: 'closed' };\n }\n\n const retainedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n if (retainedEvents >= this.options.maxQueuedEvents) {\n this.droppedCapacity += 1;\n return { kind: 'dropped', sequence, reason: 'capacity' };\n }\n\n this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence) }));\n this.scheduleDrain();\n return { kind: 'admitted', sequence };\n }\n\n attachPort(port: WoodTraceBatchPort): void {\n this.detachPort();\n this.port = port;\n this.unsubscribePort = port.subscribe((message) => this.handleAcknowledgement(message));\n if (this.inFlight) {\n this.inFlight.awaitingAcknowledgement = false;\n this.inFlight.retryReady = true;\n this.inFlight.retryGeneration += 1;\n }\n this.scheduleDrain();\n }\n\n status(): WoodTraceBatchTransportStatus {\n return Object.freeze({\n state: this.state,\n producerId: this.options.producerId,\n nextSequence: this.nextSequence,\n queuedEvents: this.queue.length,\n inFlightBatchId: this.inFlight?.batch.batchId ?? null,\n droppedCapacity: this.droppedCapacity,\n droppedClosed: this.droppedClosed,\n droppedRejected: this.droppedRejected,\n droppedRetryExhausted: this.droppedRetryExhausted,\n metadataTruncatedValues: this.metadataTruncatedValues,\n metadataRedactedValues: this.metadataRedactedValues,\n metadataSerializationFailures: this.metadataSerializationFailures,\n committedBatches: this.committedBatches,\n retryAttempts: this.retryAttempts,\n });\n }\n\n async flush(deadlineMs: number): Promise<void> {\n this.scheduleDrain();\n while (this.hasPendingEvents() && this.options.now() < deadlineMs) {\n await this.options.delay(1);\n this.scheduleDrain();\n }\n }\n\n async close(deadlineMs: number): Promise<void> {\n if (this.state === 'stopped') {\n return;\n }\n this.state = 'draining';\n await this.flush(deadlineMs);\n const abandonedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n this.droppedClosed += abandonedEvents;\n this.queue.length = 0;\n this.inFlight = null;\n this.detachPort();\n this.state = 'stopped';\n }\n\n private abandonRetryExhausted(): void {\n if (!this.inFlight) {\n return;\n }\n this.droppedRetryExhausted += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n }\n\n private createInFlightBatch(): void {\n if (this.inFlight || this.queue.length === 0 || !this.port) {\n return;\n }\n const entries = this.queue.splice(0, this.options.maxBatchEvents);\n const first = entries[0];\n if (!first) {\n return;\n }\n this.inFlight = {\n batch: this.contract.create(\n this.options.producerId,\n first.sequence,\n entries.map((entry) => entry.event),\n ),\n attempts: 0,\n awaitingAcknowledgement: false,\n retryReady: true,\n retryGeneration: 0,\n };\n }\n\n private detachPort(): void {\n this.unsubscribePort?.();\n this.unsubscribePort = null;\n this.port?.close();\n this.port = null;\n }\n\n private drain(): void {\n this.createInFlightBatch();\n this.sendInFlightBatch();\n }\n\n private handleAcknowledgement(message: unknown): void {\n const parsed = this.contract.parseAcknowledgement(message);\n if (!parsed.ok || !this.inFlight) {\n return;\n }\n const acknowledgement = parsed.acknowledgement;\n if (acknowledgement.batchId !== this.inFlight.batch.batchId) {\n return;\n }\n\n this.inFlight.retryGeneration += 1;\n this.inFlight.awaitingAcknowledgement = false;\n if (acknowledgement.kind === 'committed') {\n if (acknowledgement.acceptedEvents !== this.inFlight.batch.events.length) {\n this.scheduleRetry(0);\n return;\n }\n this.committedBatches += 1;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n if (acknowledgement.kind === 'rejected') {\n this.droppedRejected += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n this.scheduleRetry(acknowledgement.retryAfterMs);\n }\n\n private handleAcknowledgementTimeout(batchId: string, attempt: number): void {\n if (!this.inFlight\n || this.inFlight.batch.batchId !== batchId\n || this.inFlight.attempts !== attempt\n || !this.inFlight.awaitingAcknowledgement) {\n return;\n }\n this.inFlight.awaitingAcknowledgement = false;\n this.scheduleRetry(this.retryDelay(attempt));\n }\n\n private hasPendingEvents(): boolean {\n return this.queue.length > 0 || this.inFlight !== null;\n }\n\n private retryDelay(attempt: number): number {\n return this.options.retryBaseDelayMs * (2 ** Math.max(0, attempt - 1));\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) {\n return;\n }\n this.drainScheduled = true;\n this.options.schedule(() => {\n this.drainScheduled = false;\n this.drain();\n });\n }\n\n private scheduleRetry(requestedDelayMs: number): void {\n if (!this.inFlight) {\n return;\n }\n if (this.inFlight.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n this.inFlight.retryReady = false;\n const generation = this.inFlight.retryGeneration + 1;\n this.inFlight.retryGeneration = generation;\n const delayMs = Math.max(requestedDelayMs, this.retryDelay(this.inFlight.attempts));\n void this.options.delay(delayMs).then(() => {\n if (!this.inFlight || this.inFlight.retryGeneration !== generation) {\n return;\n }\n this.inFlight.retryReady = true;\n this.scheduleDrain();\n });\n }\n\n private sendInFlightBatch(): void {\n const current = this.inFlight;\n const port = this.port;\n if (!current || !port || current.awaitingAcknowledgement || !current.retryReady) {\n return;\n }\n if (current.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n current.attempts += 1;\n if (current.attempts > 1) {\n this.retryAttempts += 1;\n }\n current.awaitingAcknowledgement = true;\n current.retryReady = false;\n const attempt = current.attempts;\n try {\n port.postMessage(current.batch);\n } catch {\n current.awaitingAcknowledgement = false;\n this.detachPort();\n return;\n }\n\n void this.options.delay(this.options.acknowledgementTimeoutMs).then(() => {\n this.handleAcknowledgementTimeout(current.batch.batchId, attempt);\n });\n }\n\n private snapshotEvent(\n event: WoodRendererTraceInput,\n sequence: number,\n ): WoodRendererTraceEvent {\n const snapshot = this.metadataSnapshotter.snapshot(event);\n this.metadataTruncatedValues += snapshot.stats.truncatedValues;\n this.metadataRedactedValues += snapshot.stats.redactedValues;\n this.metadataSerializationFailures += snapshot.stats.serializationFailures;\n const input = snapshot.metadata;\n const occurredAt = new Date(this.options.now());\n const timestamp = Number.isNaN(occurredAt.getTime())\n ? new Date(0).toISOString()\n : occurredAt.toISOString();\n return Object.freeze({\n source: this.snapshotString(input.source, 'unknown'),\n type: this.snapshotString(input.type, 'unknown'),\n level: this.snapshotString(input.level, 'info'),\n process: 'renderer',\n timestamp,\n traceSeq: sequence + 1,\n ...this.snapshotOptionalString('message', input.message),\n ...this.snapshotConversationId(input.conversationId),\n ...this.snapshotPayload(input.payload),\n ...this.snapshotOptionalString('windowId', input.windowId),\n ...this.snapshotOptionalNumber('webContentsId', input.webContentsId),\n ...this.snapshotOptionalString('routeKey', input.routeKey),\n ...this.snapshotOptionalString('harnessId', input.harnessId),\n });\n }\n\n private snapshotConversationId(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'conversationId'> | Record<string, never> {\n return typeof value === 'string' || typeof value === 'number'\n ? { conversationId: value }\n : {};\n }\n\n private snapshotOptionalNumber<Key extends 'webContentsId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'number' && Number.isFinite(value)\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotOptionalString<Key extends 'message' | 'windowId' | 'routeKey' | 'harnessId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'string'\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotPayload(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'payload'> | Record<string, never> {\n if (value === undefined) {\n return {};\n }\n const payload: TelemetryJsonObject = this.isJsonObject(value)\n ? value\n : Object.freeze({ __telemetry: value });\n return { payload };\n }\n\n private snapshotString(value: TelemetryJsonValue | undefined, fallback: string): string {\n return typeof value === 'string' && value.trim().length > 0 ? value : fallback;\n }\n\n private isJsonObject(value: TelemetryJsonValue): value is TelemetryJsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private validateOptions(): void {\n const validCapacity = Number.isSafeInteger(this.options.maxQueuedEvents)\n && this.options.maxQueuedEvents > 0\n && Number.isSafeInteger(this.options.maxBatchEvents)\n && this.options.maxBatchEvents > 0\n && this.options.maxBatchEvents <= this.options.maxQueuedEvents;\n const validRetry = Number.isSafeInteger(this.options.retryLimit)\n && this.options.retryLimit >= 0\n && Number.isFinite(this.options.retryBaseDelayMs)\n && this.options.retryBaseDelayMs >= 0\n && Number.isFinite(this.options.acknowledgementTimeoutMs)\n && this.options.acknowledgementTimeoutMs > 0;\n if (!this.options.producerId.trim() || !validCapacity || !validRetry) {\n throw new Error('Renderer trace batch transport options are invalid');\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/tracing/renderer_trace_batch_transport.ts"],"sourcesContent":["import {\n BoundedMetadataSnapshotter,\n DEFAULT_METADATA_SNAPSHOT_LIMITS,\n type TelemetryJsonObject,\n type TelemetryJsonValue,\n} from '@noego/telemetry/core';\nimport { WoodTraceBatchContract } from './wood_trace_batch_contract.js';\nimport type {\n WoodRendererTraceEvent,\n WoodRendererTraceInput,\n WoodTraceBatch,\n WoodTraceBatchAdmissionResult,\n WoodTraceBatchPort,\n WoodTraceBatchTransportOptions,\n WoodTraceBatchTransportStatus,\n} from './types/wood_trace_batch.types.js';\n\ntype QueuedTraceEvent = Readonly<{\n sequence: number;\n event: WoodRendererTraceEvent;\n}>;\n\ntype InFlightTraceBatch = {\n batch: WoodTraceBatch;\n attempts: number;\n awaitingAcknowledgement: boolean;\n retryReady: boolean;\n retryGeneration: number;\n};\n\nexport class RendererTraceBatchTransport {\n private readonly contract = new WoodTraceBatchContract();\n private readonly metadataSnapshotter: BoundedMetadataSnapshotter;\n private readonly queue: QueuedTraceEvent[] = [];\n private state: 'accepting' | 'draining' | 'stopped' = 'accepting';\n private port: WoodTraceBatchPort | null = null;\n private unsubscribePort: (() => void) | null = null;\n private inFlight: InFlightTraceBatch | null = null;\n private nextSequence = 0;\n private drainScheduled = false;\n private droppedCapacity = 0;\n private droppedClosed = 0;\n private droppedRejected = 0;\n private droppedRetryExhausted = 0;\n private identityRestamped = 0;\n private committedBatches = 0;\n private retryAttempts = 0;\n private metadataTruncatedValues = 0;\n private metadataRedactedValues = 0;\n private metadataSerializationFailures = 0;\n\n constructor(private readonly options: WoodTraceBatchTransportOptions) {\n this.validateOptions();\n this.metadataSnapshotter = new BoundedMetadataSnapshotter(\n options.metadataSnapshotLimits ?? DEFAULT_METADATA_SNAPSHOT_LIMITS,\n );\n }\n\n admit(event: WoodRendererTraceInput): WoodTraceBatchAdmissionResult {\n const identity = this.resolveIdentity(event);\n const sequence = identity.sequence;\n if (this.state !== 'accepting') {\n this.droppedClosed += 1;\n return { kind: 'dropped', sequence, reason: 'closed' };\n }\n\n const retainedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n if (retainedEvents >= this.options.maxQueuedEvents) {\n this.droppedCapacity += 1;\n return { kind: 'dropped', sequence, reason: 'capacity' };\n }\n\n this.queue.push(Object.freeze({ sequence, event: this.snapshotEvent(event, sequence, identity) }));\n this.scheduleDrain();\n return { kind: 'admitted', sequence };\n }\n\n /**\n * Resolves the queue sequence and preserved identity for an incoming event,\n * reading identity fields from the raw input BEFORE metadata snapshotting so\n * truncation/redaction can never alter identity.\n *\n * A hub-admitted event (valid timestamp + traceSeq) keeps its identity and\n * its queue sequence is derived as traceSeq - 1 so the batch sequence range\n * stays aligned with hub identity. A stamped event whose traceSeq regresses\n * against the already-assigned sequence stream is restamped as legacy (its\n * occurrence timestamp is still preserved, its producerId is dropped so a\n * reassigned sequence cannot masquerade under the durable identity key) and\n * counted in identityRestamped. Legacy events without identity are stamped\n * exactly as before.\n */\n private resolveIdentity(event: WoodRendererTraceInput): {\n sequence: number;\n timestamp?: string;\n producerId?: string;\n } {\n const rawTimestamp = typeof event.timestamp === 'string'\n && Number.isFinite(Date.parse(event.timestamp))\n ? event.timestamp\n : undefined;\n const rawSeq = typeof event.traceSeq === 'number'\n && Number.isSafeInteger(event.traceSeq)\n && event.traceSeq >= 1\n ? event.traceSeq\n : undefined;\n const producerId = typeof event.producerId === 'string' && event.producerId.trim().length > 0\n ? event.producerId\n : undefined;\n\n if (rawTimestamp !== undefined && rawSeq !== undefined && rawSeq - 1 >= this.nextSequence) {\n this.nextSequence = rawSeq;\n return {\n sequence: rawSeq - 1,\n timestamp: rawTimestamp,\n ...(producerId !== undefined ? { producerId } : {}),\n };\n }\n\n if (rawTimestamp !== undefined && rawSeq !== undefined) {\n // Stamped but non-monotonic against this transport's sequence stream:\n // protocol survival wins, durable sequence identity is sacrificed loudly.\n this.identityRestamped += 1;\n }\n\n const sequence = this.nextSequence;\n this.nextSequence += 1;\n return {\n sequence,\n ...(rawTimestamp !== undefined ? { timestamp: rawTimestamp } : {}),\n };\n }\n\n attachPort(port: WoodTraceBatchPort): void {\n this.detachPort();\n this.port = port;\n this.unsubscribePort = port.subscribe((message) => this.handleAcknowledgement(message));\n if (this.inFlight) {\n this.inFlight.awaitingAcknowledgement = false;\n this.inFlight.retryReady = true;\n this.inFlight.retryGeneration += 1;\n }\n this.scheduleDrain();\n }\n\n status(): WoodTraceBatchTransportStatus {\n return Object.freeze({\n state: this.state,\n producerId: this.options.producerId,\n nextSequence: this.nextSequence,\n queuedEvents: this.queue.length,\n inFlightBatchId: this.inFlight?.batch.batchId ?? null,\n droppedCapacity: this.droppedCapacity,\n droppedClosed: this.droppedClosed,\n droppedRejected: this.droppedRejected,\n droppedRetryExhausted: this.droppedRetryExhausted,\n identityRestamped: this.identityRestamped,\n metadataTruncatedValues: this.metadataTruncatedValues,\n metadataRedactedValues: this.metadataRedactedValues,\n metadataSerializationFailures: this.metadataSerializationFailures,\n committedBatches: this.committedBatches,\n retryAttempts: this.retryAttempts,\n });\n }\n\n async flush(deadlineMs: number): Promise<void> {\n this.scheduleDrain();\n while (this.hasPendingEvents() && this.options.now() < deadlineMs) {\n await this.options.delay(1);\n this.scheduleDrain();\n }\n }\n\n async close(deadlineMs: number): Promise<void> {\n if (this.state === 'stopped') {\n return;\n }\n this.state = 'draining';\n await this.flush(deadlineMs);\n const abandonedEvents = this.queue.length + (this.inFlight?.batch.events.length ?? 0);\n this.droppedClosed += abandonedEvents;\n this.queue.length = 0;\n this.inFlight = null;\n this.detachPort();\n this.state = 'stopped';\n }\n\n private abandonRetryExhausted(): void {\n if (!this.inFlight) {\n return;\n }\n this.droppedRetryExhausted += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n }\n\n private createInFlightBatch(): void {\n if (this.inFlight || this.queue.length === 0 || !this.port) {\n return;\n }\n const entries = this.queue.splice(0, this.options.maxBatchEvents);\n const first = entries[0];\n if (!first) {\n return;\n }\n this.inFlight = {\n batch: this.contract.create(\n this.options.producerId,\n first.sequence,\n entries.map((entry) => entry.event),\n ),\n attempts: 0,\n awaitingAcknowledgement: false,\n retryReady: true,\n retryGeneration: 0,\n };\n }\n\n private detachPort(): void {\n this.unsubscribePort?.();\n this.unsubscribePort = null;\n this.port?.close();\n this.port = null;\n }\n\n private drain(): void {\n this.createInFlightBatch();\n this.sendInFlightBatch();\n }\n\n private handleAcknowledgement(message: unknown): void {\n const parsed = this.contract.parseAcknowledgement(message);\n if (!parsed.ok || !this.inFlight) {\n return;\n }\n const acknowledgement = parsed.acknowledgement;\n if (acknowledgement.batchId !== this.inFlight.batch.batchId) {\n return;\n }\n\n this.inFlight.retryGeneration += 1;\n this.inFlight.awaitingAcknowledgement = false;\n if (acknowledgement.kind === 'committed') {\n if (acknowledgement.acceptedEvents !== this.inFlight.batch.events.length) {\n this.scheduleRetry(0);\n return;\n }\n this.committedBatches += 1;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n if (acknowledgement.kind === 'rejected') {\n this.droppedRejected += this.inFlight.batch.events.length;\n this.inFlight = null;\n this.scheduleDrain();\n return;\n }\n this.scheduleRetry(acknowledgement.retryAfterMs);\n }\n\n private handleAcknowledgementTimeout(batchId: string, attempt: number): void {\n if (!this.inFlight\n || this.inFlight.batch.batchId !== batchId\n || this.inFlight.attempts !== attempt\n || !this.inFlight.awaitingAcknowledgement) {\n return;\n }\n this.inFlight.awaitingAcknowledgement = false;\n this.scheduleRetry(this.retryDelay(attempt));\n }\n\n private hasPendingEvents(): boolean {\n return this.queue.length > 0 || this.inFlight !== null;\n }\n\n private retryDelay(attempt: number): number {\n return this.options.retryBaseDelayMs * (2 ** Math.max(0, attempt - 1));\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) {\n return;\n }\n this.drainScheduled = true;\n this.options.schedule(() => {\n this.drainScheduled = false;\n this.drain();\n });\n }\n\n private scheduleRetry(requestedDelayMs: number): void {\n if (!this.inFlight) {\n return;\n }\n if (this.inFlight.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n this.inFlight.retryReady = false;\n const generation = this.inFlight.retryGeneration + 1;\n this.inFlight.retryGeneration = generation;\n const delayMs = Math.max(requestedDelayMs, this.retryDelay(this.inFlight.attempts));\n void this.options.delay(delayMs).then(() => {\n if (!this.inFlight || this.inFlight.retryGeneration !== generation) {\n return;\n }\n this.inFlight.retryReady = true;\n this.scheduleDrain();\n });\n }\n\n private sendInFlightBatch(): void {\n const current = this.inFlight;\n const port = this.port;\n if (!current || !port || current.awaitingAcknowledgement || !current.retryReady) {\n return;\n }\n if (current.attempts > this.options.retryLimit) {\n this.abandonRetryExhausted();\n return;\n }\n\n current.attempts += 1;\n if (current.attempts > 1) {\n this.retryAttempts += 1;\n }\n current.awaitingAcknowledgement = true;\n current.retryReady = false;\n const attempt = current.attempts;\n try {\n port.postMessage(current.batch);\n } catch {\n current.awaitingAcknowledgement = false;\n this.detachPort();\n return;\n }\n\n void this.options.delay(this.options.acknowledgementTimeoutMs).then(() => {\n this.handleAcknowledgementTimeout(current.batch.batchId, attempt);\n });\n }\n\n private snapshotEvent(\n event: WoodRendererTraceInput,\n sequence: number,\n identity: { timestamp?: string; producerId?: string },\n ): WoodRendererTraceEvent {\n const snapshot = this.metadataSnapshotter.snapshot(event);\n this.metadataTruncatedValues += snapshot.stats.truncatedValues;\n this.metadataRedactedValues += snapshot.stats.redactedValues;\n this.metadataSerializationFailures += snapshot.stats.serializationFailures;\n const input = snapshot.metadata;\n // A hub-preserved occurrence timestamp is authoritative; only legacy\n // unstamped events receive a transport-stamped time.\n let timestamp = identity.timestamp;\n if (timestamp === undefined) {\n const occurredAt = new Date(this.options.now());\n timestamp = Number.isNaN(occurredAt.getTime())\n ? new Date(0).toISOString()\n : occurredAt.toISOString();\n }\n return Object.freeze({\n source: this.snapshotString(input.source, 'unknown'),\n type: this.snapshotString(input.type, 'unknown'),\n level: this.snapshotString(input.level, 'info'),\n process: 'renderer',\n timestamp,\n traceSeq: sequence + 1,\n ...(identity.producerId !== undefined ? { producerId: identity.producerId } : {}),\n ...this.snapshotOptionalString('message', input.message),\n ...this.snapshotConversationId(input.conversationId),\n ...this.snapshotPayload(input.payload),\n ...this.snapshotOptionalString('windowId', input.windowId),\n ...this.snapshotOptionalNumber('webContentsId', input.webContentsId),\n ...this.snapshotOptionalString('routeKey', input.routeKey),\n ...this.snapshotOptionalString('harnessId', input.harnessId),\n });\n }\n\n private snapshotConversationId(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'conversationId'> | Record<string, never> {\n return typeof value === 'string' || typeof value === 'number'\n ? { conversationId: value }\n : {};\n }\n\n private snapshotOptionalNumber<Key extends 'webContentsId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'number' && Number.isFinite(value)\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotOptionalString<Key extends 'message' | 'windowId' | 'routeKey' | 'harnessId'>(\n key: Key,\n value: TelemetryJsonValue | undefined,\n ): Partial<Pick<WoodRendererTraceEvent, Key>> {\n return typeof value === 'string'\n ? { [key]: value } as Pick<WoodRendererTraceEvent, Key>\n : {};\n }\n\n private snapshotPayload(\n value: TelemetryJsonValue | undefined,\n ): Pick<WoodRendererTraceEvent, 'payload'> | Record<string, never> {\n if (value === undefined) {\n return {};\n }\n const payload: TelemetryJsonObject = this.isJsonObject(value)\n ? value\n : Object.freeze({ __telemetry: value });\n return { payload };\n }\n\n private snapshotString(value: TelemetryJsonValue | undefined, fallback: string): string {\n return typeof value === 'string' && value.trim().length > 0 ? value : fallback;\n }\n\n private isJsonObject(value: TelemetryJsonValue): value is TelemetryJsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private validateOptions(): void {\n const validCapacity = Number.isSafeInteger(this.options.maxQueuedEvents)\n && this.options.maxQueuedEvents > 0\n && Number.isSafeInteger(this.options.maxBatchEvents)\n && this.options.maxBatchEvents > 0\n && this.options.maxBatchEvents <= this.options.maxQueuedEvents;\n const validRetry = Number.isSafeInteger(this.options.retryLimit)\n && this.options.retryLimit >= 0\n && Number.isFinite(this.options.retryBaseDelayMs)\n && this.options.retryBaseDelayMs >= 0\n && Number.isFinite(this.options.acknowledgementTimeoutMs)\n && this.options.acknowledgementTimeoutMs > 0;\n if (!this.options.producerId.trim() || !validCapacity || !validRetry) {\n throw new Error('Renderer trace batch transport options are invalid');\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,110 @@
|
|
|
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 trace_batch_adapter_exports = {};
|
|
20
|
+
__export(trace_batch_adapter_exports, {
|
|
21
|
+
woodBatchToTraceBatch: () => woodBatchToTraceBatch
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(trace_batch_adapter_exports);
|
|
24
|
+
var import_trace = require("@noego/trace");
|
|
25
|
+
function woodBatchToTraceBatch(batch, context = {}, options = {}) {
|
|
26
|
+
if (batch.events.length === 0) {
|
|
27
|
+
return { ok: false, reason: "Wood trace batch is empty" };
|
|
28
|
+
}
|
|
29
|
+
const producerId = resolveUniformProducerId(batch);
|
|
30
|
+
const records = [];
|
|
31
|
+
let previousSequence = 0;
|
|
32
|
+
for (const event of batch.events) {
|
|
33
|
+
const occurredAtMs = Date.parse(event.timestamp);
|
|
34
|
+
if (!Number.isFinite(occurredAtMs)) {
|
|
35
|
+
return { ok: false, reason: `Wood trace event timestamp is invalid: '${event.timestamp}'` };
|
|
36
|
+
}
|
|
37
|
+
if (!Number.isSafeInteger(event.traceSeq) || event.traceSeq < 1) {
|
|
38
|
+
return { ok: false, reason: `Wood trace event sequence is invalid: ${event.traceSeq}` };
|
|
39
|
+
}
|
|
40
|
+
if (event.traceSeq <= previousSequence) {
|
|
41
|
+
return { ok: false, reason: "Wood trace event sequences are not strictly increasing" };
|
|
42
|
+
}
|
|
43
|
+
previousSequence = event.traceSeq;
|
|
44
|
+
records.push(convertEvent(event, producerId, occurredAtMs, context));
|
|
45
|
+
}
|
|
46
|
+
const first = records[0];
|
|
47
|
+
const last = records[records.length - 1];
|
|
48
|
+
if (!first || !last) {
|
|
49
|
+
return { ok: false, reason: "Wood trace batch is empty" };
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
batch: Object.freeze({
|
|
54
|
+
schemaVersion: 1,
|
|
55
|
+
batchId: batch.batchId,
|
|
56
|
+
producerId,
|
|
57
|
+
sequenceStart: first.sequence,
|
|
58
|
+
sequenceEnd: last.sequence,
|
|
59
|
+
createdAtMs: options.createdAtMs ?? Date.now(),
|
|
60
|
+
records: Object.freeze(records)
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function resolveUniformProducerId(batch) {
|
|
65
|
+
const first = batch.events[0]?.producerId;
|
|
66
|
+
if (typeof first === "string" && first.trim().length > 0) {
|
|
67
|
+
const uniform = batch.events.every((event) => event.producerId === first);
|
|
68
|
+
if (uniform) {
|
|
69
|
+
return first;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return `wood:${batch.producerId}`;
|
|
73
|
+
}
|
|
74
|
+
function convertEvent(event, producerId, occurredAtMs, context) {
|
|
75
|
+
const extras = {
|
|
76
|
+
...event.payload ?? {}
|
|
77
|
+
};
|
|
78
|
+
const merged = { ...pickRuntimeContext(event), ...context };
|
|
79
|
+
if (merged.windowId !== void 0) extras.windowId = merged.windowId;
|
|
80
|
+
if (merged.webContentsId !== void 0) extras.webContentsId = merged.webContentsId;
|
|
81
|
+
if (merged.routeKey !== void 0) extras.routeKey = merged.routeKey;
|
|
82
|
+
if (merged.harnessId !== void 0) extras.harnessId = merged.harnessId;
|
|
83
|
+
return Object.freeze({
|
|
84
|
+
id: `${producerId}:${event.traceSeq}`,
|
|
85
|
+
occurredAtMs,
|
|
86
|
+
timestamp: occurredAtMs,
|
|
87
|
+
producerId,
|
|
88
|
+
sequence: event.traceSeq,
|
|
89
|
+
source: event.source,
|
|
90
|
+
event: event.type,
|
|
91
|
+
level: (0, import_trace.parseTraceLevel)(event.level),
|
|
92
|
+
process: event.process,
|
|
93
|
+
...event.conversationId !== void 0 ? { conversationId: event.conversationId } : {},
|
|
94
|
+
...typeof event.message === "string" ? { message: event.message } : {},
|
|
95
|
+
...Object.keys(extras).length > 0 ? { context: Object.freeze(extras) } : {}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function pickRuntimeContext(event) {
|
|
99
|
+
return {
|
|
100
|
+
...event.windowId !== void 0 ? { windowId: event.windowId } : {},
|
|
101
|
+
...event.webContentsId !== void 0 ? { webContentsId: event.webContentsId } : {},
|
|
102
|
+
...event.routeKey !== void 0 ? { routeKey: event.routeKey } : {},
|
|
103
|
+
...event.harnessId !== void 0 ? { harnessId: event.harnessId } : {}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
107
|
+
0 && (module.exports = {
|
|
108
|
+
woodBatchToTraceBatch
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=trace_batch_adapter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tracing/trace_batch_adapter.ts"],"sourcesContent":["import type { AdmittedTraceEvent, TraceBatch } from '@noego/trace';\nimport { parseTraceLevel } from '@noego/trace';\nimport type {\n WoodRendererTraceEvent,\n WoodTraceBatch,\n WoodTraceBatchRuntimeContext,\n} from './types/wood_trace_batch.types.js';\n\nexport type WoodTraceBatchConversion =\n | { ok: true; batch: TraceBatch }\n | { ok: false; reason: string };\n\n/**\n * Converts a validated Wood renderer trace batch into the @noego/trace\n * TraceBatch contract for the SQLite batch receiver.\n *\n * Identity is preserved, never regenerated:\n * - occurredAtMs = the event's producer-assigned ISO timestamp, parsed;\n * - sequence = the event's hub traceSeq (Wood batch ranges are queue\n * sequences, i.e. traceSeq - 1, so the converted range shifts by +1);\n * - producerId = the hub producerId when every event carries the same one,\n * else a 'wood:<preload-session>' fallback uniformly for the whole batch\n * (the TraceBatch contract requires one producer per batch);\n * - id = '<producerId>:<sequence>' — deterministic, stable across retries;\n * - batchId is reused verbatim so receiver-side duplicate detection keys on\n * the same delivery identity the renderer retries with.\n *\n * Runtime context (windowId/webContentsId/routeKey/harnessId) merges into the\n * event context without touching identity fields.\n */\nexport function woodBatchToTraceBatch(\n batch: WoodTraceBatch,\n context: WoodTraceBatchRuntimeContext = {},\n options: { createdAtMs?: number } = {},\n): WoodTraceBatchConversion {\n if (batch.events.length === 0) {\n return { ok: false, reason: 'Wood trace batch is empty' };\n }\n\n const producerId = resolveUniformProducerId(batch);\n\n const records: AdmittedTraceEvent[] = [];\n let previousSequence = 0;\n for (const event of batch.events) {\n const occurredAtMs = Date.parse(event.timestamp);\n if (!Number.isFinite(occurredAtMs)) {\n return { ok: false, reason: `Wood trace event timestamp is invalid: '${event.timestamp}'` };\n }\n if (!Number.isSafeInteger(event.traceSeq) || event.traceSeq < 1) {\n return { ok: false, reason: `Wood trace event sequence is invalid: ${event.traceSeq}` };\n }\n if (event.traceSeq <= previousSequence) {\n return { ok: false, reason: 'Wood trace event sequences are not strictly increasing' };\n }\n previousSequence = event.traceSeq;\n records.push(convertEvent(event, producerId, occurredAtMs, context));\n }\n\n const first = records[0];\n const last = records[records.length - 1];\n if (!first || !last) {\n return { ok: false, reason: 'Wood trace batch is empty' };\n }\n\n return {\n ok: true,\n batch: Object.freeze({\n schemaVersion: 1,\n batchId: batch.batchId,\n producerId,\n sequenceStart: first.sequence,\n sequenceEnd: last.sequence,\n createdAtMs: options.createdAtMs ?? Date.now(),\n records: Object.freeze(records),\n }),\n };\n}\n\nfunction resolveUniformProducerId(batch: WoodTraceBatch): string {\n const first = batch.events[0]?.producerId;\n if (typeof first === 'string' && first.trim().length > 0) {\n const uniform = batch.events.every((event) => event.producerId === first);\n if (uniform) {\n return first;\n }\n }\n return `wood:${batch.producerId}`;\n}\n\nfunction convertEvent(\n event: WoodRendererTraceEvent,\n producerId: string,\n occurredAtMs: number,\n context: WoodTraceBatchRuntimeContext,\n): AdmittedTraceEvent {\n const extras: Record<string, unknown> = {\n ...(event.payload ?? {}),\n };\n const merged: WoodTraceBatchRuntimeContext = { ...pickRuntimeContext(event), ...context };\n if (merged.windowId !== undefined) extras.windowId = merged.windowId;\n if (merged.webContentsId !== undefined) extras.webContentsId = merged.webContentsId;\n if (merged.routeKey !== undefined) extras.routeKey = merged.routeKey;\n if (merged.harnessId !== undefined) extras.harnessId = merged.harnessId;\n\n return Object.freeze({\n id: `${producerId}:${event.traceSeq}`,\n occurredAtMs,\n timestamp: occurredAtMs,\n producerId,\n sequence: event.traceSeq,\n source: event.source,\n event: event.type,\n level: parseTraceLevel(event.level),\n process: event.process,\n ...(event.conversationId !== undefined ? { conversationId: event.conversationId } : {}),\n ...(typeof event.message === 'string' ? { message: event.message } : {}),\n ...(Object.keys(extras).length > 0 ? { context: Object.freeze(extras) } : {}),\n }) as AdmittedTraceEvent;\n}\n\nfunction pickRuntimeContext(event: WoodRendererTraceEvent): WoodTraceBatchRuntimeContext {\n return {\n ...(event.windowId !== undefined ? { windowId: event.windowId } : {}),\n ...(event.webContentsId !== undefined ? { webContentsId: event.webContentsId } : {}),\n ...(event.routeKey !== undefined ? { routeKey: event.routeKey } : {}),\n ...(event.harnessId !== undefined ? { harnessId: event.harnessId } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|