@noego/wood 0.4.10 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -42
- package/dist/bridge/backend_bridge.cjs.map +1 -1
- package/dist/bridge/backend_bridge.js.map +1 -1
- package/dist/client/index.cjs +78 -21
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +18 -3
- package/dist/client/index.d.ts +18 -3
- package/dist/client/index.js +80 -22
- package/dist/client/index.js.map +1 -1
- package/dist/client/renderer_log_transport.cjs +151 -0
- package/dist/client/renderer_log_transport.cjs.map +1 -0
- package/dist/client/renderer_log_transport.d.cts +54 -0
- package/dist/client/renderer_log_transport.d.ts +54 -0
- package/dist/client/renderer_log_transport.js +123 -0
- package/dist/client/renderer_log_transport.js.map +1 -0
- package/dist/codegen/controller_registration_generator.cjs +13 -2
- package/dist/codegen/controller_registration_generator.cjs.map +1 -1
- package/dist/codegen/controller_registration_generator.d.cts +12 -1
- package/dist/codegen/controller_registration_generator.d.ts +12 -1
- package/dist/codegen/controller_registration_generator.js +10 -1
- package/dist/codegen/controller_registration_generator.js.map +1 -1
- package/dist/codegen/index.d.cts +1 -0
- package/dist/codegen/index.d.ts +1 -0
- package/dist/codegen/preload_generator.cjs +13 -6
- package/dist/codegen/preload_generator.cjs.map +1 -1
- package/dist/codegen/preload_generator.d.cts +11 -2
- package/dist/codegen/preload_generator.d.ts +11 -2
- package/dist/codegen/preload_generator.js +13 -6
- package/dist/codegen/preload_generator.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +78 -42
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +78 -42
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/codegen/type_generator.cjs +1 -0
- package/dist/codegen/type_generator.cjs.map +1 -1
- package/dist/codegen/type_generator.js +1 -0
- package/dist/codegen/type_generator.js.map +1 -1
- package/dist/config/config_parser.cjs +95 -4
- package/dist/config/config_parser.cjs.map +1 -1
- package/dist/config/config_parser.d.cts +10 -2
- package/dist/config/config_parser.d.ts +10 -2
- package/dist/config/config_parser.js +92 -3
- package/dist/config/config_parser.js.map +1 -1
- package/dist/config/index.cjs +6 -2
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.cts +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +8 -2
- package/dist/config/index.js.map +1 -1
- package/dist/controller/controller_resolver.cjs +51 -3
- package/dist/controller/controller_resolver.cjs.map +1 -1
- package/dist/controller/controller_resolver.d.cts +27 -4
- package/dist/controller/controller_resolver.d.ts +27 -4
- package/dist/controller/controller_resolver.js +48 -2
- package/dist/controller/controller_resolver.js.map +1 -1
- package/dist/controller/index.cjs +6 -2
- package/dist/controller/index.cjs.map +1 -1
- package/dist/controller/index.d.cts +1 -1
- package/dist/controller/index.d.ts +1 -1
- package/dist/controller/index.js +4 -2
- package/dist/controller/index.js.map +1 -1
- package/dist/dev/wood_dev_server.cjs +4 -1
- package/dist/dev/wood_dev_server.cjs.map +1 -1
- package/dist/dev/wood_dev_server.js +5 -2
- package/dist/dev/wood_dev_server.js.map +1 -1
- package/dist/dev/yaml_watcher.cjs +1 -1
- package/dist/dev/yaml_watcher.cjs.map +1 -1
- package/dist/dev/yaml_watcher.d.cts +4 -0
- package/dist/dev/yaml_watcher.d.ts +4 -0
- package/dist/dev/yaml_watcher.js +1 -1
- package/dist/dev/yaml_watcher.js.map +1 -1
- package/dist/frontend/frontend_lifecycle.cjs +74 -0
- package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
- package/dist/frontend/frontend_lifecycle.d.cts +50 -0
- package/dist/frontend/frontend_lifecycle.d.ts +50 -0
- package/dist/frontend/frontend_lifecycle.js +50 -0
- package/dist/frontend/frontend_lifecycle.js.map +1 -0
- package/dist/frontend/frontend_page.cjs +122 -0
- package/dist/frontend/frontend_page.cjs.map +1 -0
- package/dist/frontend/frontend_page.d.cts +62 -0
- package/dist/frontend/frontend_page.d.ts +62 -0
- package/dist/frontend/frontend_page.js +98 -0
- package/dist/frontend/frontend_page.js.map +1 -0
- package/dist/frontend/frontend_surface.cjs +249 -0
- package/dist/frontend/frontend_surface.cjs.map +1 -0
- package/dist/frontend/frontend_surface.d.cts +64 -0
- package/dist/frontend/frontend_surface.d.ts +64 -0
- package/dist/frontend/frontend_surface.js +224 -0
- package/dist/frontend/frontend_surface.js.map +1 -0
- package/dist/frontend/index.cjs +52 -0
- package/dist/frontend/index.cjs.map +1 -0
- package/dist/frontend/index.d.cts +10 -0
- package/dist/frontend/index.d.ts +10 -0
- package/dist/frontend/index.js +19 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/page_catalog.cjs +135 -0
- package/dist/frontend/page_catalog.cjs.map +1 -0
- package/dist/frontend/page_catalog.d.cts +56 -0
- package/dist/frontend/page_catalog.d.ts +56 -0
- package/dist/frontend/page_catalog.js +108 -0
- package/dist/frontend/page_catalog.js.map +1 -0
- package/dist/frontend/tracked_transport.cjs +55 -0
- package/dist/frontend/tracked_transport.cjs.map +1 -0
- package/dist/frontend/tracked_transport.d.cts +36 -0
- package/dist/frontend/tracked_transport.d.ts +36 -0
- package/dist/frontend/tracked_transport.js +31 -0
- package/dist/frontend/tracked_transport.js.map +1 -0
- package/dist/frontend/work_registry.cjs +153 -0
- package/dist/frontend/work_registry.cjs.map +1 -0
- package/dist/frontend/work_registry.d.cts +70 -0
- package/dist/frontend/work_registry.d.ts +70 -0
- package/dist/frontend/work_registry.js +128 -0
- package/dist/frontend/work_registry.js.map +1 -0
- package/dist/index.cjs +24 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -7
- package/dist/index.d.ts +10 -7
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/dist/main/index.cjs +10 -0
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +14 -2
- package/dist/main/index.d.ts +14 -2
- package/dist/main/index.js +16 -0
- package/dist/main/index.js.map +1 -1
- package/dist/middleware/middleware_resolver.cjs +22 -1
- package/dist/middleware/middleware_resolver.cjs.map +1 -1
- package/dist/middleware/middleware_resolver.d.cts +13 -1
- package/dist/middleware/middleware_resolver.d.ts +13 -1
- package/dist/middleware/middleware_resolver.js +22 -1
- package/dist/middleware/middleware_resolver.js.map +1 -1
- package/dist/navigation/index.cjs +3 -0
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +25 -1
- package/dist/navigation/index.d.ts +25 -1
- package/dist/navigation/index.js +2 -0
- package/dist/navigation/index.js.map +1 -1
- package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
- package/dist/navigation/layout_preservation.cjs.map +1 -0
- package/dist/navigation/layout_preservation.d.cts +2 -0
- package/dist/navigation/layout_preservation.d.ts +2 -0
- package/dist/navigation/layout_preservation.js +18 -0
- package/dist/navigation/layout_preservation.js.map +1 -0
- package/dist/parser/index.cjs +2 -0
- package/dist/parser/index.cjs.map +1 -1
- package/dist/parser/index.d.cts +1 -1
- package/dist/parser/index.d.ts +1 -1
- package/dist/parser/index.js +2 -1
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/operations_parser.cjs +6 -0
- package/dist/parser/operations_parser.cjs.map +1 -1
- package/dist/parser/operations_parser.d.cts +9 -2
- package/dist/parser/operations_parser.d.ts +9 -2
- package/dist/parser/operations_parser.js +5 -0
- package/dist/parser/operations_parser.js.map +1 -1
- package/dist/parser/views_parser.cjs.map +1 -1
- package/dist/parser/views_parser.js.map +1 -1
- package/dist/router/index.d.cts +1 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/router/wood_router.cjs +35 -3
- package/dist/router/wood_router.cjs.map +1 -1
- package/dist/router/wood_router.d.cts +15 -0
- package/dist/router/wood_router.d.ts +15 -0
- package/dist/router/wood_router.js +36 -4
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/get_container.cjs +9 -34
- package/dist/runtime/get_container.cjs.map +1 -1
- package/dist/runtime/get_container.d.cts +24 -4
- package/dist/runtime/get_container.d.ts +24 -4
- package/dist/runtime/get_container.js +8 -23
- package/dist/runtime/get_container.js.map +1 -1
- package/dist/runtime/index.cjs +9 -0
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +5 -2
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +10 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderer_config_extension.cjs +50 -0
- package/dist/runtime/renderer_config_extension.cjs.map +1 -0
- package/dist/runtime/renderer_config_extension.d.cts +19 -0
- package/dist/runtime/renderer_config_extension.d.ts +19 -0
- package/dist/runtime/renderer_config_extension.js +24 -0
- package/dist/runtime/renderer_config_extension.js.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
- package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
- package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
- package/dist/runtime/renderer_log_batch_receiver.js +48 -0
- package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
- package/dist/runtime/runtime.cjs +14 -0
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +2 -1
- package/dist/runtime/runtime.d.ts +2 -1
- package/dist/runtime/runtime.js +14 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/stick/index.cjs.map +1 -1
- package/dist/stick/index.js.map +1 -1
- package/dist/testing/browser.cjs +104 -23
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +8 -3
- package/dist/testing/browser.d.ts +8 -3
- package/dist/testing/browser.js +102 -22
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.cjs +28 -8
- package/dist/testing/create_controller_harness.cjs.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +17 -2
- package/dist/testing/create_controller_harness.d.ts +17 -2
- package/dist/testing/create_controller_harness.js +28 -8
- package/dist/testing/create_controller_harness.js.map +1 -1
- package/dist/testing/create_router_bridge.d.cts +1 -0
- package/dist/testing/create_router_bridge.d.ts +1 -0
- package/dist/testing/create_test_router.d.cts +1 -0
- package/dist/testing/create_test_router.d.ts +1 -0
- package/dist/testing/index.cjs +31 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +20 -5
- package/dist/testing/index.d.ts +20 -5
- package/dist/testing/index.js +19 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
- package/dist/testing/test_wood.cjs.map +1 -0
- package/dist/testing/test_wood.d.cts +16 -0
- package/dist/testing/test_wood.d.ts +16 -0
- package/dist/testing/test_wood.js +12 -0
- package/dist/testing/test_wood.js.map +1 -0
- package/dist/testing/test_wood_config.cjs +272 -0
- package/dist/testing/test_wood_config.cjs.map +1 -0
- package/dist/testing/test_wood_config.d.cts +111 -0
- package/dist/testing/test_wood_config.d.ts +111 -0
- package/dist/testing/test_wood_config.js +247 -0
- package/dist/testing/test_wood_config.js.map +1 -0
- package/dist/testing/wood_config_source.cjs +146 -0
- package/dist/testing/wood_config_source.cjs.map +1 -0
- package/dist/testing/wood_config_source.d.cts +36 -0
- package/dist/testing/wood_config_source.d.ts +36 -0
- package/dist/testing/wood_config_source.js +112 -0
- package/dist/testing/wood_config_source.js.map +1 -0
- package/dist/testing/wood_env_renderer.cjs +210 -0
- package/dist/testing/wood_env_renderer.cjs.map +1 -0
- package/dist/testing/wood_env_renderer.d.cts +74 -0
- package/dist/testing/wood_env_renderer.d.ts +74 -0
- package/dist/testing/wood_env_renderer.js +188 -0
- package/dist/testing/wood_env_renderer.js.map +1 -0
- package/dist/testing/wood_test_selection.cjs +94 -0
- package/dist/testing/wood_test_selection.cjs.map +1 -0
- package/dist/testing/wood_test_selection.d.cts +39 -0
- package/dist/testing/wood_test_selection.d.ts +39 -0
- package/dist/testing/wood_test_selection.js +68 -0
- package/dist/testing/wood_test_selection.js.map +1 -0
- package/dist/trace-testing/index.d.cts +1 -2
- package/dist/trace-testing/index.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.cjs +1 -1
- package/dist/trace-testing/trace_recorder.cjs.map +1 -1
- package/dist/trace-testing/trace_recorder.d.cts +1 -2
- package/dist/trace-testing/trace_recorder.d.ts +1 -2
- package/dist/trace-testing/trace_recorder.js +1 -1
- package/dist/trace-testing/trace_recorder.js.map +1 -1
- package/dist/trace-transport/index.d.cts +1 -1
- package/dist/trace-transport/index.d.ts +1 -1
- package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
- package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
- package/dist/tracing/index.cjs +9 -2
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +3 -2
- package/dist/tracing/index.d.ts +3 -2
- package/dist/tracing/index.js +7 -1
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
- package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
- package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
- package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
- package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
- package/dist/tracing/renderer_trace_batch_transport.js +48 -6
- package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
- package/dist/tracing/trace_batch_adapter.cjs +110 -0
- package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
- package/dist/tracing/trace_batch_adapter.d.cts +36 -0
- package/dist/tracing/trace_batch_adapter.d.ts +36 -0
- package/dist/tracing/trace_batch_adapter.js +86 -0
- package/dist/tracing/trace_batch_adapter.js.map +1 -0
- package/dist/tracing/trace_commit_writer.d.cts +1 -1
- package/dist/tracing/trace_commit_writer.d.ts +1 -1
- package/dist/tracing/trace_hub.cjs +87 -20
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +1 -1
- package/dist/tracing/trace_hub.d.ts +1 -1
- package/dist/tracing/trace_hub.js +85 -20
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +21 -6
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +13 -4
- package/dist/tracing/trace_provider.d.ts +13 -4
- package/dist/tracing/trace_provider.js +22 -7
- package/dist/tracing/trace_provider.js.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
- package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
- package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
- package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
- package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
- package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
- package/dist/tracing/wood_trace_batch_contract.js +2 -0
- package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
- package/dist/transport/build_transport_bridge.cjs +4 -2
- package/dist/transport/build_transport_bridge.cjs.map +1 -1
- package/dist/transport/build_transport_bridge.d.cts +7 -1
- package/dist/transport/build_transport_bridge.d.ts +7 -1
- package/dist/transport/build_transport_bridge.js +2 -1
- package/dist/transport/build_transport_bridge.js.map +1 -1
- package/dist/transport/in_process_router_transport.d.cts +1 -0
- package/dist/transport/in_process_router_transport.d.ts +1 -0
- package/dist/transport/index.d.cts +1 -0
- package/dist/transport/index.d.ts +1 -0
- package/dist/types/config.cjs.map +1 -1
- package/dist/types/config.d.cts +47 -1
- package/dist/types/config.d.ts +47 -1
- package/dist/types/context.cjs +12 -0
- package/dist/types/context.cjs.map +1 -1
- package/dist/types/context.d.cts +27 -1
- package/dist/types/context.d.ts +27 -1
- package/dist/types/context.js +4 -0
- package/dist/types/context.js.map +1 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/operations.cjs.map +1 -1
- package/dist/types/operations.d.cts +2 -0
- package/dist/types/operations.d.ts +2 -0
- package/docs/axe.md +706 -0
- package/package.json +13 -5
- package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
- package/src/components/NavigationShell.svelte +126 -49
- package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
- package/dist/controller/__fixtures__/controllers/chat.js +0 -12
- package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
- package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
- package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
- package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
- package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.cjs +0 -29
- package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
- package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
- package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
- package/dist/controller/__fixtures__/controllers/test.js +0 -9
- package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.cjs +0 -27
- package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
- package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
- package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.cjs +0 -27
- package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
- package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
- package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
- package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
- package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
- package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.cjs +0 -47
- package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
- package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
- package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
- package/dist/middleware/__fixtures__/middleware/sequence.js.map +0 -1
|
@@ -1 +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":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAgC;AA6BzB,SAAS,sBACd,OACA,UAAwC,CAAC,GACzC,UAAoC,CAAC,GACX;AAC1B,MAAI,MAAM,OAAO,WAAW,GAAG;AAC7B,WAAO,EAAE,IAAI,OAAO,QAAQ,4BAA4B;AAAA,EAC1D;AAEA,QAAM,aAAa,yBAAyB,KAAK;AAEjD,QAAM,UAAgC,CAAC;AACvC,MAAI,mBAAmB;AACvB,aAAW,SAAS,MAAM,QAAQ;AAChC,UAAM,eAAe,KAAK,MAAM,MAAM,SAAS;AAC/C,QAAI,CAAC,OAAO,SAAS,YAAY,GAAG;AAClC,aAAO,EAAE,IAAI,OAAO,QAAQ,2CAA2C,MAAM,SAAS,IAAI;AAAA,IAC5F;AACA,QAAI,CAAC,OAAO,cAAc,MAAM,QAAQ,KAAK,MAAM,WAAW,GAAG;AAC/D,aAAO,EAAE,IAAI,OAAO,QAAQ,yCAAyC,MAAM,QAAQ,GAAG;AAAA,IACxF;AACA,QAAI,MAAM,YAAY,kBAAkB;AACtC,aAAO,EAAE,IAAI,OAAO,QAAQ,yDAAyD;AAAA,IACvF;AACA,uBAAmB,MAAM;AACzB,YAAQ,KAAK,aAAa,OAAO,YAAY,cAAc,OAAO,CAAC;AAAA,EACrE;AAEA,QAAM,QAAQ,QAAQ,CAAC;AACvB,QAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,WAAO,EAAE,IAAI,OAAO,QAAQ,4BAA4B;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO,OAAO,OAAO;AAAA,MACnB,eAAe;AAAA,MACf,SAAS,MAAM;AAAA,MACf;AAAA,MACA,eAAe,MAAM;AAAA,MACrB,aAAa,KAAK;AAAA,MAClB,aAAa,QAAQ,eAAe,KAAK,IAAI;AAAA,MAC7C,SAAS,OAAO,OAAO,OAAO;AAAA,IAChC,CAAC;AAAA,EACH;AACF;AAEA,SAAS,yBAAyB,OAA+B;AAC/D,QAAM,QAAQ,MAAM,OAAO,CAAC,GAAG;AAC/B,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AACxD,UAAM,UAAU,MAAM,OAAO,MAAM,CAAC,UAAU,MAAM,eAAe,KAAK;AACxE,QAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,QAAQ,MAAM,UAAU;AACjC;AAEA,SAAS,aACP,OACA,YACA,cACA,SACoB;AACpB,QAAM,SAAkC;AAAA,IACtC,GAAI,MAAM,WAAW,CAAC;AAAA,EACxB;AACA,QAAM,SAAuC,EAAE,GAAG,mBAAmB,KAAK,GAAG,GAAG,QAAQ;AACxF,MAAI,OAAO,aAAa,OAAW,QAAO,WAAW,OAAO;AAC5D,MAAI,OAAO,kBAAkB,OAAW,QAAO,gBAAgB,OAAO;AACtE,MAAI,OAAO,aAAa,OAAW,QAAO,WAAW,OAAO;AAC5D,MAAI,OAAO,cAAc,OAAW,QAAO,YAAY,OAAO;AAE9D,SAAO,OAAO,OAAO;AAAA,IACnB,IAAI,GAAG,UAAU,IAAI,MAAM,QAAQ;AAAA,IACnC;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM;AAAA,IACb,WAAO,8BAAgB,MAAM,KAAK;AAAA,IAClC,SAAS,MAAM;AAAA,IACf,GAAI,MAAM,mBAAmB,SAAY,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,IACrF,GAAI,OAAO,MAAM,YAAY,WAAW,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,IACtE,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,EAAE,SAAS,OAAO,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,EAC7E,CAAC;AACH;AAEA,SAAS,mBAAmB,OAA6D;AACvF,SAAO;AAAA,IACL,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IACnE,GAAI,MAAM,kBAAkB,SAAY,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;AAAA,IAClF,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IACnE,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,EACxE;AACF;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TraceBatch } from '@noego/trace';
|
|
2
|
+
import { WoodTraceBatch, WoodTraceBatchRuntimeContext } from './types/wood_trace_batch.types.cjs';
|
|
3
|
+
import '@noego/telemetry/core';
|
|
4
|
+
import '../trace_hub-Cpo_nVze.cjs';
|
|
5
|
+
import 'rxjs';
|
|
6
|
+
|
|
7
|
+
type WoodTraceBatchConversion = {
|
|
8
|
+
ok: true;
|
|
9
|
+
batch: TraceBatch;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
reason: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Converts a validated Wood renderer trace batch into the @noego/trace
|
|
16
|
+
* TraceBatch contract for the SQLite batch receiver.
|
|
17
|
+
*
|
|
18
|
+
* Identity is preserved, never regenerated:
|
|
19
|
+
* - occurredAtMs = the event's producer-assigned ISO timestamp, parsed;
|
|
20
|
+
* - sequence = the event's hub traceSeq (Wood batch ranges are queue
|
|
21
|
+
* sequences, i.e. traceSeq - 1, so the converted range shifts by +1);
|
|
22
|
+
* - producerId = the hub producerId when every event carries the same one,
|
|
23
|
+
* else a 'wood:<preload-session>' fallback uniformly for the whole batch
|
|
24
|
+
* (the TraceBatch contract requires one producer per batch);
|
|
25
|
+
* - id = '<producerId>:<sequence>' — deterministic, stable across retries;
|
|
26
|
+
* - batchId is reused verbatim so receiver-side duplicate detection keys on
|
|
27
|
+
* the same delivery identity the renderer retries with.
|
|
28
|
+
*
|
|
29
|
+
* Runtime context (windowId/webContentsId/routeKey/harnessId) merges into the
|
|
30
|
+
* event context without touching identity fields.
|
|
31
|
+
*/
|
|
32
|
+
declare function woodBatchToTraceBatch(batch: WoodTraceBatch, context?: WoodTraceBatchRuntimeContext, options?: {
|
|
33
|
+
createdAtMs?: number;
|
|
34
|
+
}): WoodTraceBatchConversion;
|
|
35
|
+
|
|
36
|
+
export { type WoodTraceBatchConversion, woodBatchToTraceBatch };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TraceBatch } from '@noego/trace';
|
|
2
|
+
import { WoodTraceBatch, WoodTraceBatchRuntimeContext } from './types/wood_trace_batch.types.js';
|
|
3
|
+
import '@noego/telemetry/core';
|
|
4
|
+
import '../trace_hub-Cpo_nVze.js';
|
|
5
|
+
import 'rxjs';
|
|
6
|
+
|
|
7
|
+
type WoodTraceBatchConversion = {
|
|
8
|
+
ok: true;
|
|
9
|
+
batch: TraceBatch;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
reason: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Converts a validated Wood renderer trace batch into the @noego/trace
|
|
16
|
+
* TraceBatch contract for the SQLite batch receiver.
|
|
17
|
+
*
|
|
18
|
+
* Identity is preserved, never regenerated:
|
|
19
|
+
* - occurredAtMs = the event's producer-assigned ISO timestamp, parsed;
|
|
20
|
+
* - sequence = the event's hub traceSeq (Wood batch ranges are queue
|
|
21
|
+
* sequences, i.e. traceSeq - 1, so the converted range shifts by +1);
|
|
22
|
+
* - producerId = the hub producerId when every event carries the same one,
|
|
23
|
+
* else a 'wood:<preload-session>' fallback uniformly for the whole batch
|
|
24
|
+
* (the TraceBatch contract requires one producer per batch);
|
|
25
|
+
* - id = '<producerId>:<sequence>' — deterministic, stable across retries;
|
|
26
|
+
* - batchId is reused verbatim so receiver-side duplicate detection keys on
|
|
27
|
+
* the same delivery identity the renderer retries with.
|
|
28
|
+
*
|
|
29
|
+
* Runtime context (windowId/webContentsId/routeKey/harnessId) merges into the
|
|
30
|
+
* event context without touching identity fields.
|
|
31
|
+
*/
|
|
32
|
+
declare function woodBatchToTraceBatch(batch: WoodTraceBatch, context?: WoodTraceBatchRuntimeContext, options?: {
|
|
33
|
+
createdAtMs?: number;
|
|
34
|
+
}): WoodTraceBatchConversion;
|
|
35
|
+
|
|
36
|
+
export { type WoodTraceBatchConversion, woodBatchToTraceBatch };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { parseTraceLevel } from "@noego/trace";
|
|
2
|
+
function woodBatchToTraceBatch(batch, context = {}, options = {}) {
|
|
3
|
+
if (batch.events.length === 0) {
|
|
4
|
+
return { ok: false, reason: "Wood trace batch is empty" };
|
|
5
|
+
}
|
|
6
|
+
const producerId = resolveUniformProducerId(batch);
|
|
7
|
+
const records = [];
|
|
8
|
+
let previousSequence = 0;
|
|
9
|
+
for (const event of batch.events) {
|
|
10
|
+
const occurredAtMs = Date.parse(event.timestamp);
|
|
11
|
+
if (!Number.isFinite(occurredAtMs)) {
|
|
12
|
+
return { ok: false, reason: `Wood trace event timestamp is invalid: '${event.timestamp}'` };
|
|
13
|
+
}
|
|
14
|
+
if (!Number.isSafeInteger(event.traceSeq) || event.traceSeq < 1) {
|
|
15
|
+
return { ok: false, reason: `Wood trace event sequence is invalid: ${event.traceSeq}` };
|
|
16
|
+
}
|
|
17
|
+
if (event.traceSeq <= previousSequence) {
|
|
18
|
+
return { ok: false, reason: "Wood trace event sequences are not strictly increasing" };
|
|
19
|
+
}
|
|
20
|
+
previousSequence = event.traceSeq;
|
|
21
|
+
records.push(convertEvent(event, producerId, occurredAtMs, context));
|
|
22
|
+
}
|
|
23
|
+
const first = records[0];
|
|
24
|
+
const last = records[records.length - 1];
|
|
25
|
+
if (!first || !last) {
|
|
26
|
+
return { ok: false, reason: "Wood trace batch is empty" };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
batch: Object.freeze({
|
|
31
|
+
schemaVersion: 1,
|
|
32
|
+
batchId: batch.batchId,
|
|
33
|
+
producerId,
|
|
34
|
+
sequenceStart: first.sequence,
|
|
35
|
+
sequenceEnd: last.sequence,
|
|
36
|
+
createdAtMs: options.createdAtMs ?? Date.now(),
|
|
37
|
+
records: Object.freeze(records)
|
|
38
|
+
})
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function resolveUniformProducerId(batch) {
|
|
42
|
+
const first = batch.events[0]?.producerId;
|
|
43
|
+
if (typeof first === "string" && first.trim().length > 0) {
|
|
44
|
+
const uniform = batch.events.every((event) => event.producerId === first);
|
|
45
|
+
if (uniform) {
|
|
46
|
+
return first;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return `wood:${batch.producerId}`;
|
|
50
|
+
}
|
|
51
|
+
function convertEvent(event, producerId, occurredAtMs, context) {
|
|
52
|
+
const extras = {
|
|
53
|
+
...event.payload ?? {}
|
|
54
|
+
};
|
|
55
|
+
const merged = { ...pickRuntimeContext(event), ...context };
|
|
56
|
+
if (merged.windowId !== void 0) extras.windowId = merged.windowId;
|
|
57
|
+
if (merged.webContentsId !== void 0) extras.webContentsId = merged.webContentsId;
|
|
58
|
+
if (merged.routeKey !== void 0) extras.routeKey = merged.routeKey;
|
|
59
|
+
if (merged.harnessId !== void 0) extras.harnessId = merged.harnessId;
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
id: `${producerId}:${event.traceSeq}`,
|
|
62
|
+
occurredAtMs,
|
|
63
|
+
timestamp: occurredAtMs,
|
|
64
|
+
producerId,
|
|
65
|
+
sequence: event.traceSeq,
|
|
66
|
+
source: event.source,
|
|
67
|
+
event: event.type,
|
|
68
|
+
level: parseTraceLevel(event.level),
|
|
69
|
+
process: event.process,
|
|
70
|
+
...event.conversationId !== void 0 ? { conversationId: event.conversationId } : {},
|
|
71
|
+
...typeof event.message === "string" ? { message: event.message } : {},
|
|
72
|
+
...Object.keys(extras).length > 0 ? { context: Object.freeze(extras) } : {}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function pickRuntimeContext(event) {
|
|
76
|
+
return {
|
|
77
|
+
...event.windowId !== void 0 ? { windowId: event.windowId } : {},
|
|
78
|
+
...event.webContentsId !== void 0 ? { webContentsId: event.webContentsId } : {},
|
|
79
|
+
...event.routeKey !== void 0 ? { routeKey: event.routeKey } : {},
|
|
80
|
+
...event.harnessId !== void 0 ? { harnessId: event.harnessId } : {}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
woodBatchToTraceBatch
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=trace_batch_adapter.js.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":[]}
|
|
@@ -22,6 +22,8 @@ __export(trace_hub_exports, {
|
|
|
22
22
|
dispatchRendererTracePayload: () => dispatchRendererTracePayload,
|
|
23
23
|
emitRendererTrace: () => emitRendererTrace,
|
|
24
24
|
getTraceEvents$: () => getTraceEvents$,
|
|
25
|
+
getTraceProducerId: () => getTraceProducerId,
|
|
26
|
+
ingestRemoteTraceEvent: () => ingestRemoteTraceEvent,
|
|
25
27
|
normalizeTraceLevel: () => normalizeTraceLevel,
|
|
26
28
|
publishMainTrace: () => publishMainTrace,
|
|
27
29
|
publishTestTrace: () => publishTestTrace,
|
|
@@ -55,6 +57,24 @@ function traceLevelOrder(level) {
|
|
|
55
57
|
let rendererMinLevel = "debug";
|
|
56
58
|
let rendererEnabled = false;
|
|
57
59
|
let customRendererTraceTransport = null;
|
|
60
|
+
let traceProducerId = null;
|
|
61
|
+
function randomIdSuffix() {
|
|
62
|
+
const c = globalThis.crypto;
|
|
63
|
+
if (c && typeof c.randomUUID === "function") {
|
|
64
|
+
return c.randomUUID();
|
|
65
|
+
}
|
|
66
|
+
return `${Date.now().toString(36)}-${Math.random().toString(16).slice(2)}`;
|
|
67
|
+
}
|
|
68
|
+
function getTraceProducerId() {
|
|
69
|
+
if (traceProducerId === null) {
|
|
70
|
+
const processTag = typeof process !== "undefined" && process?.versions?.electron ? process.type === "renderer" ? "renderer" : "main" : typeof window !== "undefined" ? "renderer" : "main";
|
|
71
|
+
traceProducerId = `${processTag}:${randomIdSuffix()}`;
|
|
72
|
+
}
|
|
73
|
+
return traceProducerId;
|
|
74
|
+
}
|
|
75
|
+
function hasValidRemoteIdentity(event) {
|
|
76
|
+
return typeof event.timestamp === "string" && Number.isFinite(Date.parse(event.timestamp)) && typeof event.traceSeq === "number" && Number.isSafeInteger(event.traceSeq) && event.traceSeq >= 1;
|
|
77
|
+
}
|
|
58
78
|
function normalizeTraceInput(raw) {
|
|
59
79
|
const input = raw ?? {};
|
|
60
80
|
const source = typeof input.source === "string" && input.source.trim().length > 0 ? input.source : "unknown";
|
|
@@ -113,8 +133,8 @@ class TraceHub {
|
|
|
113
133
|
get events$() {
|
|
114
134
|
return this.shared$;
|
|
115
135
|
}
|
|
116
|
-
setMinLevel(
|
|
117
|
-
this.minLevels[
|
|
136
|
+
setMinLevel(process2, level) {
|
|
137
|
+
this.minLevels[process2] = level;
|
|
118
138
|
}
|
|
119
139
|
registerSink(sink) {
|
|
120
140
|
this.sinks.add(sink);
|
|
@@ -122,36 +142,61 @@ class TraceHub {
|
|
|
122
142
|
this.sinks.delete(sink);
|
|
123
143
|
};
|
|
124
144
|
}
|
|
125
|
-
publish(
|
|
145
|
+
publish(process2, level, input) {
|
|
126
146
|
const normalized = normalizeTraceInput(input);
|
|
127
147
|
const event = {
|
|
128
148
|
...normalized,
|
|
129
149
|
level,
|
|
130
|
-
process,
|
|
150
|
+
process: process2,
|
|
131
151
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
132
|
-
traceSeq: this.nextTraceSeq
|
|
152
|
+
traceSeq: this.nextTraceSeq++,
|
|
153
|
+
producerId: getTraceProducerId()
|
|
133
154
|
};
|
|
134
|
-
if (traceLevelOrder(level) >= traceLevelOrder(this.minLevels[
|
|
155
|
+
if (traceLevelOrder(level) >= traceLevelOrder(this.minLevels[process2])) {
|
|
135
156
|
this.publishToSinks(event);
|
|
136
157
|
this.subject.next(event);
|
|
137
158
|
}
|
|
138
159
|
return event;
|
|
139
160
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Single renderer admission point: assigns timestamp, traceSeq, and
|
|
163
|
+
* producerId exactly once, then delivers the same event to sinks and
|
|
164
|
+
* events$ subscribers. The returned event is what the renderer transport
|
|
165
|
+
* must forward — no downstream stage may regenerate its identity.
|
|
166
|
+
*
|
|
167
|
+
* Callers gate on rendererEnabled/level BEFORE calling, so gated-out events
|
|
168
|
+
* consume no traceSeq.
|
|
169
|
+
*/
|
|
170
|
+
admitRenderer(level, input) {
|
|
147
171
|
const event = {
|
|
148
172
|
...input,
|
|
149
173
|
level,
|
|
150
174
|
process: "renderer",
|
|
151
175
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
152
|
-
traceSeq: this.nextTraceSeq
|
|
176
|
+
traceSeq: this.nextTraceSeq++,
|
|
177
|
+
producerId: getTraceProducerId()
|
|
153
178
|
};
|
|
154
179
|
this.publishToSinks(event);
|
|
180
|
+
this.subject.next(event);
|
|
181
|
+
return event;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Delivers an event admitted by a remote producer (e.g. a renderer event
|
|
185
|
+
* received over IPC) to this hub's sinks and events$ subscribers without
|
|
186
|
+
* reassigning identity or advancing this hub's own traceSeq counter.
|
|
187
|
+
* The min-level gate for the event's process still applies — delivery
|
|
188
|
+
* filtering is not identity assignment.
|
|
189
|
+
*/
|
|
190
|
+
ingest(event) {
|
|
191
|
+
if (event.producerId !== void 0 && event.producerId === getTraceProducerId()) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const gate = this.minLevels[event.process] ?? this.minLevels.renderer;
|
|
195
|
+
if (traceLevelOrder(event.level) < traceLevelOrder(gate)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this.publishToSinks(event);
|
|
199
|
+
this.subject.next(event);
|
|
155
200
|
}
|
|
156
201
|
publishToSinks(event) {
|
|
157
202
|
if (this.sinks.size === 0) {
|
|
@@ -195,18 +240,38 @@ function setRendererTraceEnabled(enabled) {
|
|
|
195
240
|
function publishMainTrace(level, input) {
|
|
196
241
|
return getGlobalTraceHub().publish("main", level, input);
|
|
197
242
|
}
|
|
198
|
-
function publishTestTrace(
|
|
199
|
-
return getGlobalTraceHub().publish(
|
|
243
|
+
function publishTestTrace(process2, level, input) {
|
|
244
|
+
return getGlobalTraceHub().publish(process2, level, input);
|
|
200
245
|
}
|
|
201
246
|
function dispatchRendererTracePayload(rawPayload, context) {
|
|
202
247
|
const payload = rawPayload ?? {};
|
|
203
248
|
const level = normalizeTraceLevel(payload.level);
|
|
249
|
+
if (hasValidRemoteIdentity(payload)) {
|
|
250
|
+
const merged = mergeTraceRuntimeContext(payload, context);
|
|
251
|
+
getGlobalTraceHub().ingest({
|
|
252
|
+
...merged,
|
|
253
|
+
level,
|
|
254
|
+
process: "renderer",
|
|
255
|
+
timestamp: payload.timestamp,
|
|
256
|
+
traceSeq: payload.traceSeq,
|
|
257
|
+
...typeof payload.producerId === "string" && payload.producerId.trim().length > 0 ? { producerId: payload.producerId } : {}
|
|
258
|
+
});
|
|
259
|
+
return { ok: true, forwarded: true };
|
|
260
|
+
}
|
|
204
261
|
getGlobalTraceHub().publish("renderer", level, mergeTraceRuntimeContext(payload, context));
|
|
205
262
|
return {
|
|
206
263
|
ok: true,
|
|
207
264
|
forwarded: true
|
|
208
265
|
};
|
|
209
266
|
}
|
|
267
|
+
function ingestRemoteTraceEvent(event, context) {
|
|
268
|
+
if (!hasValidRemoteIdentity(event)) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
const merged = context ? { ...mergeTraceRuntimeContext(event, context), level: event.level, process: event.process, timestamp: event.timestamp, traceSeq: event.traceSeq, ...event.producerId ? { producerId: event.producerId } : {} } : event;
|
|
272
|
+
getGlobalTraceHub().ingest(merged);
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
210
275
|
function setRendererTraceTransport(fn) {
|
|
211
276
|
customRendererTraceTransport = fn;
|
|
212
277
|
}
|
|
@@ -217,11 +282,10 @@ function emitRendererTrace(level, input) {
|
|
|
217
282
|
if (traceLevelOrder(level) < traceLevelOrder(rendererMinLevel)) {
|
|
218
283
|
return;
|
|
219
284
|
}
|
|
220
|
-
const
|
|
221
|
-
getGlobalTraceHub().publishRendererToSinks(level, normalized);
|
|
285
|
+
const event = getGlobalTraceHub().admitRenderer(level, normalizeTraceInput(input));
|
|
222
286
|
if (customRendererTraceTransport) {
|
|
223
287
|
try {
|
|
224
|
-
customRendererTraceTransport(
|
|
288
|
+
customRendererTraceTransport(event);
|
|
225
289
|
return;
|
|
226
290
|
} catch {
|
|
227
291
|
}
|
|
@@ -231,7 +295,7 @@ function emitRendererTrace(level, input) {
|
|
|
231
295
|
return;
|
|
232
296
|
}
|
|
233
297
|
try {
|
|
234
|
-
bridge.__trace(
|
|
298
|
+
bridge.__trace(event);
|
|
235
299
|
} catch {
|
|
236
300
|
}
|
|
237
301
|
}
|
|
@@ -241,6 +305,7 @@ function clearTraceHubForTests() {
|
|
|
241
305
|
rendererMinLevel = "debug";
|
|
242
306
|
rendererEnabled = false;
|
|
243
307
|
customRendererTraceTransport = null;
|
|
308
|
+
traceProducerId = null;
|
|
244
309
|
}
|
|
245
310
|
// Annotate the CommonJS export names for ESM import in node:
|
|
246
311
|
0 && (module.exports = {
|
|
@@ -248,6 +313,8 @@ function clearTraceHubForTests() {
|
|
|
248
313
|
dispatchRendererTracePayload,
|
|
249
314
|
emitRendererTrace,
|
|
250
315
|
getTraceEvents$,
|
|
316
|
+
getTraceProducerId,
|
|
317
|
+
ingestRemoteTraceEvent,
|
|
251
318
|
normalizeTraceLevel,
|
|
252
319
|
publishMainTrace,
|
|
253
320
|
publishTestTrace,
|