@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.
Files changed (493) hide show
  1. package/README.md +118 -42
  2. package/bin/axe.js +313 -98
  3. package/dist/{loader/__fixtures__/layouts/app.load.cjs → automation/actions.cjs} +3 -13
  4. package/dist/automation/actions.cjs.map +1 -0
  5. package/dist/automation/actions.d.cts +57 -0
  6. package/dist/automation/actions.d.ts +57 -0
  7. package/dist/automation/actions.js +1 -0
  8. package/dist/automation/actions.js.map +1 -0
  9. package/dist/automation/actions_executor.cjs +101 -0
  10. package/dist/automation/actions_executor.cjs.map +1 -0
  11. package/dist/automation/actions_executor.d.cts +16 -0
  12. package/dist/automation/actions_executor.d.ts +16 -0
  13. package/dist/automation/actions_executor.js +76 -0
  14. package/dist/automation/actions_executor.js.map +1 -0
  15. package/dist/automation/connection.cjs +86 -0
  16. package/dist/automation/connection.cjs.map +1 -0
  17. package/dist/automation/connection.d.cts +18 -0
  18. package/dist/automation/connection.d.ts +18 -0
  19. package/dist/automation/connection.js +51 -0
  20. package/dist/automation/connection.js.map +1 -0
  21. package/dist/{middleware/__fixtures__/middleware/sequence.cjs → automation/errors.cjs} +25 -22
  22. package/dist/automation/errors.cjs.map +1 -0
  23. package/dist/automation/errors.d.cts +31 -0
  24. package/dist/automation/errors.d.ts +31 -0
  25. package/dist/automation/errors.js +24 -0
  26. package/dist/automation/errors.js.map +1 -0
  27. package/dist/automation/index.cjs +49 -0
  28. package/dist/automation/index.cjs.map +1 -0
  29. package/dist/automation/index.d.cts +16 -0
  30. package/dist/automation/index.d.ts +16 -0
  31. package/dist/automation/index.js +15 -0
  32. package/dist/automation/index.js.map +1 -0
  33. package/dist/automation/introspection_reader.cjs +75 -0
  34. package/dist/automation/introspection_reader.cjs.map +1 -0
  35. package/dist/automation/introspection_reader.d.cts +20 -0
  36. package/dist/automation/introspection_reader.d.ts +20 -0
  37. package/dist/automation/introspection_reader.js +48 -0
  38. package/dist/automation/introspection_reader.js.map +1 -0
  39. package/dist/automation/locator.cjs +102 -0
  40. package/dist/automation/locator.cjs.map +1 -0
  41. package/dist/automation/locator.d.cts +51 -0
  42. package/dist/automation/locator.d.ts +51 -0
  43. package/dist/automation/locator.js +75 -0
  44. package/dist/automation/locator.js.map +1 -0
  45. package/dist/{loader/__fixtures__/views/test/page.load.cjs → automation/observation.cjs} +3 -13
  46. package/dist/automation/observation.cjs.map +1 -0
  47. package/dist/automation/observation.d.cts +44 -0
  48. package/dist/automation/observation.d.ts +44 -0
  49. package/dist/automation/observation.js +1 -0
  50. package/dist/automation/observation.js.map +1 -0
  51. package/dist/{controller/__fixtures__/controllers/test.cjs → automation/receipts.cjs} +3 -15
  52. package/dist/automation/receipts.cjs.map +1 -0
  53. package/dist/automation/receipts.d.cts +27 -0
  54. package/dist/automation/receipts.d.ts +27 -0
  55. package/dist/automation/receipts.js +1 -0
  56. package/dist/automation/receipts.js.map +1 -0
  57. package/dist/automation/scenario.cjs +696 -0
  58. package/dist/automation/scenario.cjs.map +1 -0
  59. package/dist/automation/scenario.d.cts +89 -0
  60. package/dist/automation/scenario.d.ts +89 -0
  61. package/dist/automation/scenario.js +660 -0
  62. package/dist/automation/scenario.js.map +1 -0
  63. package/dist/automation/scrolling.cjs +17 -0
  64. package/dist/automation/scrolling.cjs.map +1 -0
  65. package/dist/automation/scrolling.d.cts +51 -0
  66. package/dist/automation/scrolling.d.ts +51 -0
  67. package/dist/automation/scrolling.js +1 -0
  68. package/dist/automation/scrolling.js.map +1 -0
  69. package/dist/automation/scrolling_executor.cjs +109 -0
  70. package/dist/automation/scrolling_executor.cjs.map +1 -0
  71. package/dist/automation/scrolling_executor.d.cts +13 -0
  72. package/dist/automation/scrolling_executor.d.ts +13 -0
  73. package/dist/automation/scrolling_executor.js +84 -0
  74. package/dist/automation/scrolling_executor.js.map +1 -0
  75. package/dist/automation/target_identity.cjs +17 -0
  76. package/dist/automation/target_identity.cjs.map +1 -0
  77. package/dist/automation/target_identity.d.cts +28 -0
  78. package/dist/automation/target_identity.d.ts +28 -0
  79. package/dist/automation/target_identity.js +1 -0
  80. package/dist/automation/target_identity.js.map +1 -0
  81. package/dist/automation/target_registry.cjs +148 -0
  82. package/dist/automation/target_registry.cjs.map +1 -0
  83. package/dist/automation/target_registry.d.cts +32 -0
  84. package/dist/automation/target_registry.d.ts +32 -0
  85. package/dist/automation/target_registry.js +122 -0
  86. package/dist/automation/target_registry.js.map +1 -0
  87. package/dist/automation/waits.cjs +17 -0
  88. package/dist/automation/waits.cjs.map +1 -0
  89. package/dist/automation/waits.d.cts +44 -0
  90. package/dist/automation/waits.d.ts +44 -0
  91. package/dist/automation/waits.js +1 -0
  92. package/dist/automation/waits.js.map +1 -0
  93. package/dist/automation/waits_executor.cjs +104 -0
  94. package/dist/automation/waits_executor.cjs.map +1 -0
  95. package/dist/automation/waits_executor.d.cts +14 -0
  96. package/dist/automation/waits_executor.d.ts +14 -0
  97. package/dist/automation/waits_executor.js +79 -0
  98. package/dist/automation/waits_executor.js.map +1 -0
  99. package/dist/bridge/backend_bridge.cjs.map +1 -1
  100. package/dist/bridge/backend_bridge.js.map +1 -1
  101. package/dist/client/index.cjs +78 -21
  102. package/dist/client/index.cjs.map +1 -1
  103. package/dist/client/index.d.cts +19 -3
  104. package/dist/client/index.d.ts +19 -3
  105. package/dist/client/index.js +80 -22
  106. package/dist/client/index.js.map +1 -1
  107. package/dist/client/renderer_log_transport.cjs +151 -0
  108. package/dist/client/renderer_log_transport.cjs.map +1 -0
  109. package/dist/client/renderer_log_transport.d.cts +54 -0
  110. package/dist/client/renderer_log_transport.d.ts +54 -0
  111. package/dist/client/renderer_log_transport.js +123 -0
  112. package/dist/client/renderer_log_transport.js.map +1 -0
  113. package/dist/codegen/controller_registration_generator.cjs +13 -2
  114. package/dist/codegen/controller_registration_generator.cjs.map +1 -1
  115. package/dist/codegen/controller_registration_generator.d.cts +12 -1
  116. package/dist/codegen/controller_registration_generator.d.ts +12 -1
  117. package/dist/codegen/controller_registration_generator.js +10 -1
  118. package/dist/codegen/controller_registration_generator.js.map +1 -1
  119. package/dist/codegen/index.d.cts +1 -0
  120. package/dist/codegen/index.d.ts +1 -0
  121. package/dist/codegen/preload_generator.cjs +13 -6
  122. package/dist/codegen/preload_generator.cjs.map +1 -1
  123. package/dist/codegen/preload_generator.d.cts +11 -2
  124. package/dist/codegen/preload_generator.d.ts +11 -2
  125. package/dist/codegen/preload_generator.js +13 -6
  126. package/dist/codegen/preload_generator.js.map +1 -1
  127. package/dist/codegen/renderer_app_generator.cjs +95 -44
  128. package/dist/codegen/renderer_app_generator.cjs.map +1 -1
  129. package/dist/codegen/renderer_app_generator.js +95 -44
  130. package/dist/codegen/renderer_app_generator.js.map +1 -1
  131. package/dist/codegen/type_generator.cjs +1 -0
  132. package/dist/codegen/type_generator.cjs.map +1 -1
  133. package/dist/codegen/type_generator.js +1 -0
  134. package/dist/codegen/type_generator.js.map +1 -1
  135. package/dist/config/config_parser.cjs +95 -4
  136. package/dist/config/config_parser.cjs.map +1 -1
  137. package/dist/config/config_parser.d.cts +10 -2
  138. package/dist/config/config_parser.d.ts +10 -2
  139. package/dist/config/config_parser.js +92 -3
  140. package/dist/config/config_parser.js.map +1 -1
  141. package/dist/config/index.cjs +6 -2
  142. package/dist/config/index.cjs.map +1 -1
  143. package/dist/config/index.d.cts +2 -2
  144. package/dist/config/index.d.ts +2 -2
  145. package/dist/config/index.js +8 -2
  146. package/dist/config/index.js.map +1 -1
  147. package/dist/controller/controller_resolver.cjs +51 -3
  148. package/dist/controller/controller_resolver.cjs.map +1 -1
  149. package/dist/controller/controller_resolver.d.cts +27 -4
  150. package/dist/controller/controller_resolver.d.ts +27 -4
  151. package/dist/controller/controller_resolver.js +48 -2
  152. package/dist/controller/controller_resolver.js.map +1 -1
  153. package/dist/controller/index.cjs +6 -2
  154. package/dist/controller/index.cjs.map +1 -1
  155. package/dist/controller/index.d.cts +1 -1
  156. package/dist/controller/index.d.ts +1 -1
  157. package/dist/controller/index.js +4 -2
  158. package/dist/controller/index.js.map +1 -1
  159. package/dist/dev/wood_dev_server.cjs +4 -1
  160. package/dist/dev/wood_dev_server.cjs.map +1 -1
  161. package/dist/dev/wood_dev_server.js +5 -2
  162. package/dist/dev/wood_dev_server.js.map +1 -1
  163. package/dist/dev/yaml_watcher.cjs +1 -1
  164. package/dist/dev/yaml_watcher.cjs.map +1 -1
  165. package/dist/dev/yaml_watcher.d.cts +4 -0
  166. package/dist/dev/yaml_watcher.d.ts +4 -0
  167. package/dist/dev/yaml_watcher.js +1 -1
  168. package/dist/dev/yaml_watcher.js.map +1 -1
  169. package/dist/frontend/frontend_lifecycle.cjs +74 -0
  170. package/dist/frontend/frontend_lifecycle.cjs.map +1 -0
  171. package/dist/frontend/frontend_lifecycle.d.cts +50 -0
  172. package/dist/frontend/frontend_lifecycle.d.ts +50 -0
  173. package/dist/frontend/frontend_lifecycle.js +50 -0
  174. package/dist/frontend/frontend_lifecycle.js.map +1 -0
  175. package/dist/frontend/frontend_page.cjs +122 -0
  176. package/dist/frontend/frontend_page.cjs.map +1 -0
  177. package/dist/frontend/frontend_page.d.cts +62 -0
  178. package/dist/frontend/frontend_page.d.ts +62 -0
  179. package/dist/frontend/frontend_page.js +98 -0
  180. package/dist/frontend/frontend_page.js.map +1 -0
  181. package/dist/frontend/frontend_surface.cjs +249 -0
  182. package/dist/frontend/frontend_surface.cjs.map +1 -0
  183. package/dist/frontend/frontend_surface.d.cts +64 -0
  184. package/dist/frontend/frontend_surface.d.ts +64 -0
  185. package/dist/frontend/frontend_surface.js +224 -0
  186. package/dist/frontend/frontend_surface.js.map +1 -0
  187. package/dist/frontend/index.cjs +52 -0
  188. package/dist/frontend/index.cjs.map +1 -0
  189. package/dist/frontend/index.d.cts +10 -0
  190. package/dist/frontend/index.d.ts +10 -0
  191. package/dist/frontend/index.js +19 -0
  192. package/dist/frontend/index.js.map +1 -0
  193. package/dist/frontend/page_catalog.cjs +135 -0
  194. package/dist/frontend/page_catalog.cjs.map +1 -0
  195. package/dist/frontend/page_catalog.d.cts +56 -0
  196. package/dist/frontend/page_catalog.d.ts +56 -0
  197. package/dist/frontend/page_catalog.js +108 -0
  198. package/dist/frontend/page_catalog.js.map +1 -0
  199. package/dist/frontend/tracked_transport.cjs +55 -0
  200. package/dist/frontend/tracked_transport.cjs.map +1 -0
  201. package/dist/frontend/tracked_transport.d.cts +36 -0
  202. package/dist/frontend/tracked_transport.d.ts +36 -0
  203. package/dist/frontend/tracked_transport.js +31 -0
  204. package/dist/frontend/tracked_transport.js.map +1 -0
  205. package/dist/frontend/work_registry.cjs +153 -0
  206. package/dist/frontend/work_registry.cjs.map +1 -0
  207. package/dist/frontend/work_registry.d.cts +70 -0
  208. package/dist/frontend/work_registry.d.ts +70 -0
  209. package/dist/frontend/work_registry.js +128 -0
  210. package/dist/frontend/work_registry.js.map +1 -0
  211. package/dist/index.cjs +24 -0
  212. package/dist/index.cjs.map +1 -1
  213. package/dist/index.d.cts +11 -7
  214. package/dist/index.d.ts +11 -7
  215. package/dist/index.js +27 -4
  216. package/dist/index.js.map +1 -1
  217. package/dist/main/index.cjs +10 -0
  218. package/dist/main/index.cjs.map +1 -1
  219. package/dist/main/index.d.cts +14 -2
  220. package/dist/main/index.d.ts +14 -2
  221. package/dist/main/index.js +16 -0
  222. package/dist/main/index.js.map +1 -1
  223. package/dist/middleware/middleware_resolver.cjs +22 -1
  224. package/dist/middleware/middleware_resolver.cjs.map +1 -1
  225. package/dist/middleware/middleware_resolver.d.cts +13 -1
  226. package/dist/middleware/middleware_resolver.d.ts +13 -1
  227. package/dist/middleware/middleware_resolver.js +22 -1
  228. package/dist/middleware/middleware_resolver.js.map +1 -1
  229. package/dist/navigation/automation_introspection.cjs +110 -0
  230. package/dist/navigation/automation_introspection.cjs.map +1 -0
  231. package/dist/navigation/automation_introspection.d.cts +60 -0
  232. package/dist/navigation/automation_introspection.d.ts +60 -0
  233. package/dist/navigation/automation_introspection.js +85 -0
  234. package/dist/navigation/automation_introspection.js.map +1 -0
  235. package/dist/navigation/index.cjs +10 -2
  236. package/dist/navigation/index.cjs.map +1 -1
  237. package/dist/navigation/index.d.cts +27 -1
  238. package/dist/navigation/index.d.ts +27 -1
  239. package/dist/navigation/index.js +6 -1
  240. package/dist/navigation/index.js.map +1 -1
  241. package/dist/{middleware/__fixtures__/middleware/auth.cjs → navigation/layout_preservation.cjs} +18 -20
  242. package/dist/navigation/layout_preservation.cjs.map +1 -0
  243. package/dist/navigation/layout_preservation.d.cts +2 -0
  244. package/dist/navigation/layout_preservation.d.ts +2 -0
  245. package/dist/navigation/layout_preservation.js +18 -0
  246. package/dist/navigation/layout_preservation.js.map +1 -0
  247. package/dist/parser/index.cjs +2 -0
  248. package/dist/parser/index.cjs.map +1 -1
  249. package/dist/parser/index.d.cts +1 -1
  250. package/dist/parser/index.d.ts +1 -1
  251. package/dist/parser/index.js +2 -1
  252. package/dist/parser/index.js.map +1 -1
  253. package/dist/parser/operations_parser.cjs +6 -0
  254. package/dist/parser/operations_parser.cjs.map +1 -1
  255. package/dist/parser/operations_parser.d.cts +9 -2
  256. package/dist/parser/operations_parser.d.ts +9 -2
  257. package/dist/parser/operations_parser.js +5 -0
  258. package/dist/parser/operations_parser.js.map +1 -1
  259. package/dist/parser/views_parser.cjs.map +1 -1
  260. package/dist/parser/views_parser.js.map +1 -1
  261. package/dist/router/index.d.cts +1 -0
  262. package/dist/router/index.d.ts +1 -0
  263. package/dist/router/wood_router.cjs +35 -3
  264. package/dist/router/wood_router.cjs.map +1 -1
  265. package/dist/router/wood_router.d.cts +15 -0
  266. package/dist/router/wood_router.d.ts +15 -0
  267. package/dist/router/wood_router.js +36 -4
  268. package/dist/router/wood_router.js.map +1 -1
  269. package/dist/runtime/get_container.cjs +9 -34
  270. package/dist/runtime/get_container.cjs.map +1 -1
  271. package/dist/runtime/get_container.d.cts +24 -4
  272. package/dist/runtime/get_container.d.ts +24 -4
  273. package/dist/runtime/get_container.js +8 -23
  274. package/dist/runtime/get_container.js.map +1 -1
  275. package/dist/runtime/index.cjs +9 -0
  276. package/dist/runtime/index.cjs.map +1 -1
  277. package/dist/runtime/index.d.cts +5 -2
  278. package/dist/runtime/index.d.ts +5 -2
  279. package/dist/runtime/index.js +10 -1
  280. package/dist/runtime/index.js.map +1 -1
  281. package/dist/runtime/renderer_config_extension.cjs +50 -0
  282. package/dist/runtime/renderer_config_extension.cjs.map +1 -0
  283. package/dist/runtime/renderer_config_extension.d.cts +19 -0
  284. package/dist/runtime/renderer_config_extension.d.ts +19 -0
  285. package/dist/runtime/renderer_config_extension.js +24 -0
  286. package/dist/runtime/renderer_config_extension.js.map +1 -0
  287. package/dist/runtime/renderer_log_batch_receiver.cjs +73 -0
  288. package/dist/runtime/renderer_log_batch_receiver.cjs.map +1 -0
  289. package/dist/runtime/renderer_log_batch_receiver.d.cts +29 -0
  290. package/dist/runtime/renderer_log_batch_receiver.d.ts +29 -0
  291. package/dist/runtime/renderer_log_batch_receiver.js +48 -0
  292. package/dist/runtime/renderer_log_batch_receiver.js.map +1 -0
  293. package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +1 -1
  294. package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +1 -1
  295. package/dist/runtime/runtime.cjs +14 -0
  296. package/dist/runtime/runtime.cjs.map +1 -1
  297. package/dist/runtime/runtime.d.cts +2 -1
  298. package/dist/runtime/runtime.d.ts +2 -1
  299. package/dist/runtime/runtime.js +14 -0
  300. package/dist/runtime/runtime.js.map +1 -1
  301. package/dist/stick/index.cjs.map +1 -1
  302. package/dist/stick/index.js.map +1 -1
  303. package/dist/testing/automation_assertions.cjs +417 -0
  304. package/dist/testing/automation_assertions.cjs.map +1 -0
  305. package/dist/testing/automation_assertions.d.cts +44 -0
  306. package/dist/testing/automation_assertions.d.ts +44 -0
  307. package/dist/testing/automation_assertions.js +385 -0
  308. package/dist/testing/automation_assertions.js.map +1 -0
  309. package/dist/testing/browser.cjs +130 -57
  310. package/dist/testing/browser.cjs.map +1 -1
  311. package/dist/testing/browser.d.cts +10 -4
  312. package/dist/testing/browser.d.ts +10 -4
  313. package/dist/testing/browser.js +132 -53
  314. package/dist/testing/browser.js.map +1 -1
  315. package/dist/testing/create_controller_harness.cjs +28 -8
  316. package/dist/testing/create_controller_harness.cjs.map +1 -1
  317. package/dist/testing/create_controller_harness.d.cts +18 -2
  318. package/dist/testing/create_controller_harness.d.ts +18 -2
  319. package/dist/testing/create_controller_harness.js +28 -8
  320. package/dist/testing/create_controller_harness.js.map +1 -1
  321. package/dist/testing/create_router_bridge.d.cts +1 -0
  322. package/dist/testing/create_router_bridge.d.ts +1 -0
  323. package/dist/testing/create_test_router.d.cts +1 -0
  324. package/dist/testing/create_test_router.d.ts +1 -0
  325. package/dist/testing/geometry.cjs +109 -0
  326. package/dist/testing/geometry.cjs.map +1 -0
  327. package/dist/testing/geometry.d.cts +45 -0
  328. package/dist/testing/geometry.d.ts +45 -0
  329. package/dist/testing/geometry.js +79 -0
  330. package/dist/testing/geometry.js.map +1 -0
  331. package/dist/testing/index.cjs +62 -2
  332. package/dist/testing/index.cjs.map +1 -1
  333. package/dist/testing/index.d.cts +23 -4
  334. package/dist/testing/index.d.ts +23 -4
  335. package/dist/testing/index.js +50 -2
  336. package/dist/testing/index.js.map +1 -1
  337. package/dist/{controller/__fixtures__/controllers/not_a_class.cjs → testing/test_wood.cjs} +15 -7
  338. package/dist/testing/test_wood.cjs.map +1 -0
  339. package/dist/testing/test_wood.d.cts +16 -0
  340. package/dist/testing/test_wood.d.ts +16 -0
  341. package/dist/testing/test_wood.js +12 -0
  342. package/dist/testing/test_wood.js.map +1 -0
  343. package/dist/testing/test_wood_config.cjs +272 -0
  344. package/dist/testing/test_wood_config.cjs.map +1 -0
  345. package/dist/testing/test_wood_config.d.cts +111 -0
  346. package/dist/testing/test_wood_config.d.ts +111 -0
  347. package/dist/testing/test_wood_config.js +247 -0
  348. package/dist/testing/test_wood_config.js.map +1 -0
  349. package/dist/testing/wood_config_source.cjs +146 -0
  350. package/dist/testing/wood_config_source.cjs.map +1 -0
  351. package/dist/testing/wood_config_source.d.cts +36 -0
  352. package/dist/testing/wood_config_source.d.ts +36 -0
  353. package/dist/testing/wood_config_source.js +112 -0
  354. package/dist/testing/wood_config_source.js.map +1 -0
  355. package/dist/testing/wood_env_renderer.cjs +210 -0
  356. package/dist/testing/wood_env_renderer.cjs.map +1 -0
  357. package/dist/testing/wood_env_renderer.d.cts +74 -0
  358. package/dist/testing/wood_env_renderer.d.ts +74 -0
  359. package/dist/testing/wood_env_renderer.js +188 -0
  360. package/dist/testing/wood_env_renderer.js.map +1 -0
  361. package/dist/testing/wood_test_selection.cjs +94 -0
  362. package/dist/testing/wood_test_selection.cjs.map +1 -0
  363. package/dist/testing/wood_test_selection.d.cts +39 -0
  364. package/dist/testing/wood_test_selection.d.ts +39 -0
  365. package/dist/testing/wood_test_selection.js +68 -0
  366. package/dist/testing/wood_test_selection.js.map +1 -0
  367. package/dist/trace-testing/index.d.cts +1 -2
  368. package/dist/trace-testing/index.d.ts +1 -2
  369. package/dist/trace-testing/trace_recorder.cjs +1 -1
  370. package/dist/trace-testing/trace_recorder.cjs.map +1 -1
  371. package/dist/trace-testing/trace_recorder.d.cts +1 -2
  372. package/dist/trace-testing/trace_recorder.d.ts +1 -2
  373. package/dist/trace-testing/trace_recorder.js +1 -1
  374. package/dist/trace-testing/trace_recorder.js.map +1 -1
  375. package/dist/trace-transport/index.d.cts +1 -1
  376. package/dist/trace-transport/index.d.ts +1 -1
  377. package/dist/{trace_hub-Cob54qRx.d.cts → trace_hub-Cpo_nVze.d.cts} +21 -1
  378. package/dist/{trace_hub-Cob54qRx.d.ts → trace_hub-Cpo_nVze.d.ts} +21 -1
  379. package/dist/tracing/index.cjs +9 -2
  380. package/dist/tracing/index.cjs.map +1 -1
  381. package/dist/tracing/index.d.cts +3 -2
  382. package/dist/tracing/index.d.ts +3 -2
  383. package/dist/tracing/index.js +7 -1
  384. package/dist/tracing/index.js.map +1 -1
  385. package/dist/tracing/renderer_trace_batch_host.d.cts +1 -1
  386. package/dist/tracing/renderer_trace_batch_host.d.ts +1 -1
  387. package/dist/tracing/renderer_trace_batch_transport.cjs +48 -6
  388. package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -1
  389. package/dist/tracing/renderer_trace_batch_transport.d.cts +17 -1
  390. package/dist/tracing/renderer_trace_batch_transport.d.ts +17 -1
  391. package/dist/tracing/renderer_trace_batch_transport.js +48 -6
  392. package/dist/tracing/renderer_trace_batch_transport.js.map +1 -1
  393. package/dist/tracing/trace_batch_adapter.cjs +110 -0
  394. package/dist/tracing/trace_batch_adapter.cjs.map +1 -0
  395. package/dist/tracing/trace_batch_adapter.d.cts +36 -0
  396. package/dist/tracing/trace_batch_adapter.d.ts +36 -0
  397. package/dist/tracing/trace_batch_adapter.js +86 -0
  398. package/dist/tracing/trace_batch_adapter.js.map +1 -0
  399. package/dist/tracing/trace_commit_writer.d.cts +1 -1
  400. package/dist/tracing/trace_commit_writer.d.ts +1 -1
  401. package/dist/tracing/trace_hub.cjs +87 -20
  402. package/dist/tracing/trace_hub.cjs.map +1 -1
  403. package/dist/tracing/trace_hub.d.cts +1 -1
  404. package/dist/tracing/trace_hub.d.ts +1 -1
  405. package/dist/tracing/trace_hub.js +85 -20
  406. package/dist/tracing/trace_hub.js.map +1 -1
  407. package/dist/tracing/trace_provider.cjs +21 -6
  408. package/dist/tracing/trace_provider.cjs.map +1 -1
  409. package/dist/tracing/trace_provider.d.cts +13 -4
  410. package/dist/tracing/trace_provider.d.ts +13 -4
  411. package/dist/tracing/trace_provider.js +22 -7
  412. package/dist/tracing/trace_provider.js.map +1 -1
  413. package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -1
  414. package/dist/tracing/types/wood_trace_batch.types.d.cts +15 -1
  415. package/dist/tracing/types/wood_trace_batch.types.d.ts +15 -1
  416. package/dist/tracing/types/wood_trace_sink.types.d.cts +1 -1
  417. package/dist/tracing/types/wood_trace_sink.types.d.ts +1 -1
  418. package/dist/tracing/wood_trace_batch_contract.cjs +2 -0
  419. package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -1
  420. package/dist/tracing/wood_trace_batch_contract.d.cts +1 -1
  421. package/dist/tracing/wood_trace_batch_contract.d.ts +1 -1
  422. package/dist/tracing/wood_trace_batch_contract.js +2 -0
  423. package/dist/tracing/wood_trace_batch_contract.js.map +1 -1
  424. package/dist/transport/build_transport_bridge.cjs +4 -2
  425. package/dist/transport/build_transport_bridge.cjs.map +1 -1
  426. package/dist/transport/build_transport_bridge.d.cts +7 -1
  427. package/dist/transport/build_transport_bridge.d.ts +7 -1
  428. package/dist/transport/build_transport_bridge.js +2 -1
  429. package/dist/transport/build_transport_bridge.js.map +1 -1
  430. package/dist/transport/in_process_router_transport.d.cts +1 -0
  431. package/dist/transport/in_process_router_transport.d.ts +1 -0
  432. package/dist/transport/index.d.cts +1 -0
  433. package/dist/transport/index.d.ts +1 -0
  434. package/dist/types/config.cjs.map +1 -1
  435. package/dist/types/config.d.cts +47 -1
  436. package/dist/types/config.d.ts +47 -1
  437. package/dist/types/context.cjs +12 -0
  438. package/dist/types/context.cjs.map +1 -1
  439. package/dist/types/context.d.cts +27 -1
  440. package/dist/types/context.d.ts +27 -1
  441. package/dist/types/context.js +4 -0
  442. package/dist/types/context.js.map +1 -1
  443. package/dist/types/index.d.cts +2 -2
  444. package/dist/types/index.d.ts +2 -2
  445. package/dist/types/operations.cjs.map +1 -1
  446. package/dist/types/operations.d.cts +2 -0
  447. package/dist/types/operations.d.ts +2 -0
  448. package/docs/axe.md +706 -0
  449. package/package.json +19 -5
  450. package/src/components/NavigationShell.scopes.browser.test.ts +363 -0
  451. package/src/components/NavigationShell.svelte +126 -49
  452. package/dist/controller/__fixtures__/controllers/chat.cjs +0 -32
  453. package/dist/controller/__fixtures__/controllers/chat.cjs.map +0 -1
  454. package/dist/controller/__fixtures__/controllers/chat.d.cts +0 -11
  455. package/dist/controller/__fixtures__/controllers/chat.d.ts +0 -11
  456. package/dist/controller/__fixtures__/controllers/chat.js +0 -12
  457. package/dist/controller/__fixtures__/controllers/chat.js.map +0 -1
  458. package/dist/controller/__fixtures__/controllers/not_a_class.cjs.map +0 -1
  459. package/dist/controller/__fixtures__/controllers/not_a_class.d.cts +0 -3
  460. package/dist/controller/__fixtures__/controllers/not_a_class.d.ts +0 -3
  461. package/dist/controller/__fixtures__/controllers/not_a_class.js +0 -5
  462. package/dist/controller/__fixtures__/controllers/not_a_class.js.map +0 -1
  463. package/dist/controller/__fixtures__/controllers/settings.controller.cjs +0 -32
  464. package/dist/controller/__fixtures__/controllers/settings.controller.cjs.map +0 -1
  465. package/dist/controller/__fixtures__/controllers/settings.controller.d.cts +0 -12
  466. package/dist/controller/__fixtures__/controllers/settings.controller.d.ts +0 -12
  467. package/dist/controller/__fixtures__/controllers/settings.controller.js +0 -12
  468. package/dist/controller/__fixtures__/controllers/settings.controller.js.map +0 -1
  469. package/dist/controller/__fixtures__/controllers/test.cjs.map +0 -1
  470. package/dist/controller/__fixtures__/controllers/test.d.cts +0 -7
  471. package/dist/controller/__fixtures__/controllers/test.d.ts +0 -7
  472. package/dist/controller/__fixtures__/controllers/test.js +0 -9
  473. package/dist/controller/__fixtures__/controllers/test.js.map +0 -1
  474. package/dist/loader/__fixtures__/layouts/app.load.cjs.map +0 -1
  475. package/dist/loader/__fixtures__/layouts/app.load.d.cts +0 -5
  476. package/dist/loader/__fixtures__/layouts/app.load.d.ts +0 -5
  477. package/dist/loader/__fixtures__/layouts/app.load.js +0 -7
  478. package/dist/loader/__fixtures__/layouts/app.load.js.map +0 -1
  479. package/dist/loader/__fixtures__/views/test/page.load.cjs.map +0 -1
  480. package/dist/loader/__fixtures__/views/test/page.load.d.cts +0 -6
  481. package/dist/loader/__fixtures__/views/test/page.load.d.ts +0 -6
  482. package/dist/loader/__fixtures__/views/test/page.load.js +0 -7
  483. package/dist/loader/__fixtures__/views/test/page.load.js.map +0 -1
  484. package/dist/middleware/__fixtures__/middleware/auth.cjs.map +0 -1
  485. package/dist/middleware/__fixtures__/middleware/auth.d.cts +0 -6
  486. package/dist/middleware/__fixtures__/middleware/auth.d.ts +0 -6
  487. package/dist/middleware/__fixtures__/middleware/auth.js +0 -19
  488. package/dist/middleware/__fixtures__/middleware/auth.js.map +0 -1
  489. package/dist/middleware/__fixtures__/middleware/sequence.cjs.map +0 -1
  490. package/dist/middleware/__fixtures__/middleware/sequence.d.cts +0 -7
  491. package/dist/middleware/__fixtures__/middleware/sequence.d.ts +0 -7
  492. package/dist/middleware/__fixtures__/middleware/sequence.js +0 -21
  493. 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 sequence = this.nextSequence;
53
- this.nextSequence += 1;
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
- const occurredAt = new Date(this.options.now());
262
- const timestamp = Number.isNaN(occurredAt.getTime()) ? (/* @__PURE__ */ new Date(0)).toISOString() : occurredAt.toISOString();
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-Cob54qRx.cjs';
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-Cob54qRx.js';
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 sequence = this.nextSequence;
33
- this.nextSequence += 1;
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
- const occurredAt = new Date(this.options.now());
242
- const timestamp = Number.isNaN(occurredAt.getTime()) ? (/* @__PURE__ */ new Date(0)).toISOString() : occurredAt.toISOString();
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":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,8BAA8B;AAwBhC,MAAM,4BAA4B;AAAA,EAoBvC,YAA6B,SAAyC;AAAzC;AAnB7B,SAAiB,WAAW,IAAI,uBAAuB;AAEvD,SAAiB,QAA4B,CAAC;AAC9C,SAAQ,QAA8C;AACtD,SAAQ,OAAkC;AAC1C,SAAQ,kBAAuC;AAC/C,SAAQ,WAAsC;AAC9C,SAAQ,eAAe;AACvB,SAAQ,iBAAiB;AACzB,SAAQ,kBAAkB;AAC1B,SAAQ,gBAAgB;AACxB,SAAQ,kBAAkB;AAC1B,SAAQ,wBAAwB;AAChC,SAAQ,mBAAmB;AAC3B,SAAQ,gBAAgB;AACxB,SAAQ,0BAA0B;AAClC,SAAQ,yBAAyB;AACjC,SAAQ,gCAAgC;AAGtC,SAAK,gBAAgB;AACrB,SAAK,sBAAsB,IAAI;AAAA,MAC7B,QAAQ,0BAA0B;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,MAAM,OAA8D;AAClE,UAAM,WAAW,KAAK;AACtB,SAAK,gBAAgB;AACrB,QAAI,KAAK,UAAU,aAAa;AAC9B,WAAK,iBAAiB;AACtB,aAAO,EAAE,MAAM,WAAW,UAAU,QAAQ,SAAS;AAAA,IACvD;AAEA,UAAM,iBAAiB,KAAK,MAAM,UAAU,KAAK,UAAU,MAAM,OAAO,UAAU;AAClF,QAAI,kBAAkB,KAAK,QAAQ,iBAAiB;AAClD,WAAK,mBAAmB;AACxB,aAAO,EAAE,MAAM,WAAW,UAAU,QAAQ,WAAW;AAAA,IACzD;AAEA,SAAK,MAAM,KAAK,OAAO,OAAO,EAAE,UAAU,OAAO,KAAK,cAAc,OAAO,QAAQ,EAAE,CAAC,CAAC;AACvF,SAAK,cAAc;AACnB,WAAO,EAAE,MAAM,YAAY,SAAS;AAAA,EACtC;AAAA,EAEA,WAAW,MAAgC;AACzC,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,kBAAkB,KAAK,UAAU,CAAC,YAAY,KAAK,sBAAsB,OAAO,CAAC;AACtF,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,0BAA0B;AACxC,WAAK,SAAS,aAAa;AAC3B,WAAK,SAAS,mBAAmB;AAAA,IACnC;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,SAAwC;AACtC,WAAO,OAAO,OAAO;AAAA,MACnB,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK,QAAQ;AAAA,MACzB,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK,MAAM;AAAA,MACzB,iBAAiB,KAAK,UAAU,MAAM,WAAW;AAAA,MACjD,iBAAiB,KAAK;AAAA,MACtB,eAAe,KAAK;AAAA,MACpB,iBAAiB,KAAK;AAAA,MACtB,uBAAuB,KAAK;AAAA,MAC5B,yBAAyB,KAAK;AAAA,MAC9B,wBAAwB,KAAK;AAAA,MAC7B,+BAA+B,KAAK;AAAA,MACpC,kBAAkB,KAAK;AAAA,MACvB,eAAe,KAAK;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAM,YAAmC;AAC7C,SAAK,cAAc;AACnB,WAAO,KAAK,iBAAiB,KAAK,KAAK,QAAQ,IAAI,IAAI,YAAY;AACjE,YAAM,KAAK,QAAQ,MAAM,CAAC;AAC1B,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,YAAmC;AAC7C,QAAI,KAAK,UAAU,WAAW;AAC5B;AAAA,IACF;AACA,SAAK,QAAQ;AACb,UAAM,KAAK,MAAM,UAAU;AAC3B,UAAM,kBAAkB,KAAK,MAAM,UAAU,KAAK,UAAU,MAAM,OAAO,UAAU;AACnF,SAAK,iBAAiB;AACtB,SAAK,MAAM,SAAS;AACpB,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,wBAA8B;AACpC,QAAI,CAAC,KAAK,UAAU;AAClB;AAAA,IACF;AACA,SAAK,yBAAyB,KAAK,SAAS,MAAM,OAAO;AACzD,SAAK,WAAW;AAChB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,sBAA4B;AAClC,QAAI,KAAK,YAAY,KAAK,MAAM,WAAW,KAAK,CAAC,KAAK,MAAM;AAC1D;AAAA,IACF;AACA,UAAM,UAAU,KAAK,MAAM,OAAO,GAAG,KAAK,QAAQ,cAAc;AAChE,UAAM,QAAQ,QAAQ,CAAC;AACvB,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,SAAK,WAAW;AAAA,MACd,OAAO,KAAK,SAAS;AAAA,QACnB,KAAK,QAAQ;AAAA,QACb,MAAM;AAAA,QACN,QAAQ,IAAI,CAAC,UAAU,MAAM,KAAK;AAAA,MACpC;AAAA,MACA,UAAU;AAAA,MACV,yBAAyB;AAAA,MACzB,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,aAAmB;AACzB,SAAK,kBAAkB;AACvB,SAAK,kBAAkB;AACvB,SAAK,MAAM,MAAM;AACjB,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,QAAc;AACpB,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEQ,sBAAsB,SAAwB;AACpD,UAAM,SAAS,KAAK,SAAS,qBAAqB,OAAO;AACzD,QAAI,CAAC,OAAO,MAAM,CAAC,KAAK,UAAU;AAChC;AAAA,IACF;AACA,UAAM,kBAAkB,OAAO;AAC/B,QAAI,gBAAgB,YAAY,KAAK,SAAS,MAAM,SAAS;AAC3D;AAAA,IACF;AAEA,SAAK,SAAS,mBAAmB;AACjC,SAAK,SAAS,0BAA0B;AACxC,QAAI,gBAAgB,SAAS,aAAa;AACxC,UAAI,gBAAgB,mBAAmB,KAAK,SAAS,MAAM,OAAO,QAAQ;AACxE,aAAK,cAAc,CAAC;AACpB;AAAA,MACF;AACA,WAAK,oBAAoB;AACzB,WAAK,WAAW;AAChB,WAAK,cAAc;AACnB;AAAA,IACF;AACA,QAAI,gBAAgB,SAAS,YAAY;AACvC,WAAK,mBAAmB,KAAK,SAAS,MAAM,OAAO;AACnD,WAAK,WAAW;AAChB,WAAK,cAAc;AACnB;AAAA,IACF;AACA,SAAK,cAAc,gBAAgB,YAAY;AAAA,EACjD;AAAA,EAEQ,6BAA6B,SAAiB,SAAuB;AAC3E,QAAI,CAAC,KAAK,YACL,KAAK,SAAS,MAAM,YAAY,WAChC,KAAK,SAAS,aAAa,WAC3B,CAAC,KAAK,SAAS,yBAAyB;AAC3C;AAAA,IACF;AACA,SAAK,SAAS,0BAA0B;AACxC,SAAK,cAAc,KAAK,WAAW,OAAO,CAAC;AAAA,EAC7C;AAAA,EAEQ,mBAA4B;AAClC,WAAO,KAAK,MAAM,SAAS,KAAK,KAAK,aAAa;AAAA,EACpD;AAAA,EAEQ,WAAW,SAAyB;AAC1C,WAAO,KAAK,QAAQ,mBAAoB,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;AAAA,EACtE;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,gBAAgB;AACvB;AAAA,IACF;AACA,SAAK,iBAAiB;AACtB,SAAK,QAAQ,SAAS,MAAM;AAC1B,WAAK,iBAAiB;AACtB,WAAK,MAAM;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc,kBAAgC;AACpD,QAAI,CAAC,KAAK,UAAU;AAClB;AAAA,IACF;AACA,QAAI,KAAK,SAAS,WAAW,KAAK,QAAQ,YAAY;AACpD,WAAK,sBAAsB;AAC3B;AAAA,IACF;AAEA,SAAK,SAAS,aAAa;AAC3B,UAAM,aAAa,KAAK,SAAS,kBAAkB;AACnD,SAAK,SAAS,kBAAkB;AAChC,UAAM,UAAU,KAAK,IAAI,kBAAkB,KAAK,WAAW,KAAK,SAAS,QAAQ,CAAC;AAClF,SAAK,KAAK,QAAQ,MAAM,OAAO,EAAE,KAAK,MAAM;AAC1C,UAAI,CAAC,KAAK,YAAY,KAAK,SAAS,oBAAoB,YAAY;AAClE;AAAA,MACF;AACA,WAAK,SAAS,aAAa;AAC3B,WAAK,cAAc;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEQ,oBAA0B;AAChC,UAAM,UAAU,KAAK;AACrB,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,WAAW,CAAC,QAAQ,QAAQ,2BAA2B,CAAC,QAAQ,YAAY;AAC/E;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,KAAK,QAAQ,YAAY;AAC9C,WAAK,sBAAsB;AAC3B;AAAA,IACF;AAEA,YAAQ,YAAY;AACpB,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,iBAAiB;AAAA,IACxB;AACA,YAAQ,0BAA0B;AAClC,YAAQ,aAAa;AACrB,UAAM,UAAU,QAAQ;AACxB,QAAI;AACF,WAAK,YAAY,QAAQ,KAAK;AAAA,IAChC,QAAQ;AACN,cAAQ,0BAA0B;AAClC,WAAK,WAAW;AAChB;AAAA,IACF;AAEA,SAAK,KAAK,QAAQ,MAAM,KAAK,QAAQ,wBAAwB,EAAE,KAAK,MAAM;AACxE,WAAK,6BAA6B,QAAQ,MAAM,SAAS,OAAO;AAAA,IAClE,CAAC;AAAA,EACH;AAAA,EAEQ,cACN,OACA,UACwB;AACxB,UAAM,WAAW,KAAK,oBAAoB,SAAS,KAAK;AACxD,SAAK,2BAA2B,SAAS,MAAM;AAC/C,SAAK,0BAA0B,SAAS,MAAM;AAC9C,SAAK,iCAAiC,SAAS,MAAM;AACrD,UAAM,QAAQ,SAAS;AACvB,UAAM,aAAa,IAAI,KAAK,KAAK,QAAQ,IAAI,CAAC;AAC9C,UAAM,YAAY,OAAO,MAAM,WAAW,QAAQ,CAAC,KAC/C,oBAAI,KAAK,CAAC,GAAE,YAAY,IACxB,WAAW,YAAY;AAC3B,WAAO,OAAO,OAAO;AAAA,MACnB,QAAQ,KAAK,eAAe,MAAM,QAAQ,SAAS;AAAA,MACnD,MAAM,KAAK,eAAe,MAAM,MAAM,SAAS;AAAA,MAC/C,OAAO,KAAK,eAAe,MAAM,OAAO,MAAM;AAAA,MAC9C,SAAS;AAAA,MACT;AAAA,MACA,UAAU,WAAW;AAAA,MACrB,GAAG,KAAK,uBAAuB,WAAW,MAAM,OAAO;AAAA,MACvD,GAAG,KAAK,uBAAuB,MAAM,cAAc;AAAA,MACnD,GAAG,KAAK,gBAAgB,MAAM,OAAO;AAAA,MACrC,GAAG,KAAK,uBAAuB,YAAY,MAAM,QAAQ;AAAA,MACzD,GAAG,KAAK,uBAAuB,iBAAiB,MAAM,aAAa;AAAA,MACnE,GAAG,KAAK,uBAAuB,YAAY,MAAM,QAAQ;AAAA,MACzD,GAAG,KAAK,uBAAuB,aAAa,MAAM,SAAS;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA,EAEQ,uBACN,OACwE;AACxE,WAAO,OAAO,UAAU,YAAY,OAAO,UAAU,WACjD,EAAE,gBAAgB,MAAM,IACxB,CAAC;AAAA,EACP;AAAA,EAEQ,uBACN,KACA,OAC4C;AAC5C,WAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IACrD,EAAE,CAAC,GAAG,GAAG,MAAM,IACf,CAAC;AAAA,EACP;AAAA,EAEQ,uBACN,KACA,OAC4C;AAC5C,WAAO,OAAO,UAAU,WACpB,EAAE,CAAC,GAAG,GAAG,MAAM,IACf,CAAC;AAAA,EACP;AAAA,EAEQ,gBACN,OACiE;AACjE,QAAI,UAAU,QAAW;AACvB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,UAA+B,KAAK,aAAa,KAAK,IACxD,QACA,OAAO,OAAO,EAAE,aAAa,MAAM,CAAC;AACxC,WAAO,EAAE,QAAQ;AAAA,EACnB;AAAA,EAEQ,eAAe,OAAuC,UAA0B;AACtF,WAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,EACxE;AAAA,EAEQ,aAAa,OAAyD;AAC5E,WAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAAA,EAC5E;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,gBAAgB,OAAO,cAAc,KAAK,QAAQ,eAAe,KAClE,KAAK,QAAQ,kBAAkB,KAC/B,OAAO,cAAc,KAAK,QAAQ,cAAc,KAChD,KAAK,QAAQ,iBAAiB,KAC9B,KAAK,QAAQ,kBAAkB,KAAK,QAAQ;AACjD,UAAM,aAAa,OAAO,cAAc,KAAK,QAAQ,UAAU,KAC1D,KAAK,QAAQ,cAAc,KAC3B,OAAO,SAAS,KAAK,QAAQ,gBAAgB,KAC7C,KAAK,QAAQ,oBAAoB,KACjC,OAAO,SAAS,KAAK,QAAQ,wBAAwB,KACrD,KAAK,QAAQ,2BAA2B;AAC7C,QAAI,CAAC,KAAK,QAAQ,WAAW,KAAK,KAAK,CAAC,iBAAiB,CAAC,YAAY;AACpE,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAAA,EACF;AACF;","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":[]}