@smoothbricks/lmao 0.1.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 (447) hide show
  1. package/README.md +269 -0
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/bun/preload.d.ts +11 -0
  4. package/dist/bun/preload.d.ts.map +1 -0
  5. package/dist/bun/preload.js +10 -0
  6. package/dist/bun/trace-preload.d.ts +8 -0
  7. package/dist/bun/trace-preload.d.ts.map +1 -0
  8. package/dist/bun/trace-preload.js +12 -0
  9. package/dist/es.d.ts +8 -0
  10. package/dist/es.d.ts.map +1 -0
  11. package/dist/es.js +9 -0
  12. package/dist/index.d.ts +41 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +84 -0
  15. package/dist/lib/JsBufferStrategy.d.ts +49 -0
  16. package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
  17. package/dist/lib/JsBufferStrategy.js +60 -0
  18. package/dist/lib/archive/chunkCompaction.d.ts +15 -0
  19. package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
  20. package/dist/lib/archive/chunkCompaction.js +24 -0
  21. package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
  22. package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
  23. package/dist/lib/archive/chunkEnvelope.js +55 -0
  24. package/dist/lib/archive/chunkRouting.d.ts +10 -0
  25. package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
  26. package/dist/lib/archive/chunkRouting.js +47 -0
  27. package/dist/lib/archive/chunkStats.d.ts +12 -0
  28. package/dist/lib/archive/chunkStats.d.ts.map +1 -0
  29. package/dist/lib/archive/chunkStats.js +10 -0
  30. package/dist/lib/archive/index.d.ts +5 -0
  31. package/dist/lib/archive/index.d.ts.map +1 -0
  32. package/dist/lib/archive/index.js +4 -0
  33. package/dist/lib/arrow/capacityStats.d.ts +9 -0
  34. package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
  35. package/dist/lib/arrow/capacityStats.js +231 -0
  36. package/dist/lib/arrow/dictionaries.d.ts +27 -0
  37. package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
  38. package/dist/lib/arrow/dictionaries.js +135 -0
  39. package/dist/lib/arrow/flechette.d.ts +40 -0
  40. package/dist/lib/arrow/flechette.d.ts.map +1 -0
  41. package/dist/lib/arrow/flechette.js +67 -0
  42. package/dist/lib/arrow/utils.d.ts +38 -0
  43. package/dist/lib/arrow/utils.d.ts.map +1 -0
  44. package/dist/lib/arrow/utils.js +112 -0
  45. package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
  46. package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
  47. package/dist/lib/buffer/Nanoseconds.js +86 -0
  48. package/dist/lib/bufferStrategy.d.ts +95 -0
  49. package/dist/lib/bufferStrategy.d.ts.map +1 -0
  50. package/dist/lib/bufferStrategy.js +1 -0
  51. package/dist/lib/capacityTuning.d.ts +50 -0
  52. package/dist/lib/capacityTuning.d.ts.map +1 -0
  53. package/dist/lib/capacityTuning.js +65 -0
  54. package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
  55. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
  56. package/dist/lib/codegen/evaluatorGenerator.js +199 -0
  57. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
  58. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
  59. package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
  60. package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
  61. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
  62. package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
  63. package/dist/lib/convertToArrow.d.ts +40 -0
  64. package/dist/lib/convertToArrow.d.ts.map +1 -0
  65. package/dist/lib/convertToArrow.js +1467 -0
  66. package/dist/lib/defineOpContext.d.ts +96 -0
  67. package/dist/lib/defineOpContext.d.ts.map +1 -0
  68. package/dist/lib/defineOpContext.js +227 -0
  69. package/dist/lib/errors/Blocked.d.ts +113 -0
  70. package/dist/lib/errors/Blocked.d.ts.map +1 -0
  71. package/dist/lib/errors/Blocked.js +68 -0
  72. package/dist/lib/errors/CodeError.d.ts +101 -0
  73. package/dist/lib/errors/CodeError.d.ts.map +1 -0
  74. package/dist/lib/errors/CodeError.js +42 -0
  75. package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
  76. package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
  77. package/dist/lib/errors/RetriesExhausted.js +31 -0
  78. package/dist/lib/errors/Transient.d.ts +115 -0
  79. package/dist/lib/errors/Transient.d.ts.map +1 -0
  80. package/dist/lib/errors/Transient.js +54 -0
  81. package/dist/lib/errors/index.d.ts +14 -0
  82. package/dist/lib/errors/index.d.ts.map +1 -0
  83. package/dist/lib/errors/index.js +16 -0
  84. package/dist/lib/errors/retry-policy.d.ts +60 -0
  85. package/dist/lib/errors/retry-policy.d.ts.map +1 -0
  86. package/dist/lib/errors/retry-policy.js +54 -0
  87. package/dist/lib/flushScheduler.d.ts +162 -0
  88. package/dist/lib/flushScheduler.d.ts.map +1 -0
  89. package/dist/lib/flushScheduler.js +388 -0
  90. package/dist/lib/library.d.ts +149 -0
  91. package/dist/lib/library.d.ts.map +1 -0
  92. package/dist/lib/library.js +588 -0
  93. package/dist/lib/logApi.d.ts +61 -0
  94. package/dist/lib/logApi.d.ts.map +1 -0
  95. package/dist/lib/logApi.js +12 -0
  96. package/dist/lib/logBinding.d.ts +63 -0
  97. package/dist/lib/logBinding.d.ts.map +1 -0
  98. package/dist/lib/logBinding.js +1 -0
  99. package/dist/lib/op.d.ts +105 -0
  100. package/dist/lib/op.d.ts.map +1 -0
  101. package/dist/lib/op.js +59 -0
  102. package/dist/lib/opContext/contextTypes.d.ts +88 -0
  103. package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
  104. package/dist/lib/opContext/contextTypes.js +34 -0
  105. package/dist/lib/opContext/createOpGroup.d.ts +57 -0
  106. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
  107. package/dist/lib/opContext/createOpGroup.js +341 -0
  108. package/dist/lib/opContext/defineOp.d.ts +83 -0
  109. package/dist/lib/opContext/defineOp.d.ts.map +1 -0
  110. package/dist/lib/opContext/defineOp.js +197 -0
  111. package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
  112. package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
  113. package/dist/lib/opContext/featureFlagTypes.js +1 -0
  114. package/dist/lib/opContext/index.d.ts +13 -0
  115. package/dist/lib/opContext/index.d.ts.map +1 -0
  116. package/dist/lib/opContext/index.js +15 -0
  117. package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
  118. package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
  119. package/dist/lib/opContext/opGroupTypes.js +31 -0
  120. package/dist/lib/opContext/opTypes.d.ts +48 -0
  121. package/dist/lib/opContext/opTypes.d.ts.map +1 -0
  122. package/dist/lib/opContext/opTypes.js +7 -0
  123. package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
  124. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
  125. package/dist/lib/opContext/spanContextTypes.js +1 -0
  126. package/dist/lib/opContext/types.d.ts +297 -0
  127. package/dist/lib/opContext/types.d.ts.map +1 -0
  128. package/dist/lib/opContext/types.js +16 -0
  129. package/dist/lib/result.d.ts +308 -0
  130. package/dist/lib/result.d.ts.map +1 -0
  131. package/dist/lib/result.js +359 -0
  132. package/dist/lib/schema/LogSchema.d.ts +62 -0
  133. package/dist/lib/schema/LogSchema.d.ts.map +1 -0
  134. package/dist/lib/schema/LogSchema.js +134 -0
  135. package/dist/lib/schema/builder.d.ts +12 -0
  136. package/dist/lib/schema/builder.d.ts.map +1 -0
  137. package/dist/lib/schema/builder.js +169 -0
  138. package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
  139. package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
  140. package/dist/lib/schema/defineFeatureFlags.js +29 -0
  141. package/dist/lib/schema/defineLogSchema.d.ts +87 -0
  142. package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
  143. package/dist/lib/schema/defineLogSchema.js +171 -0
  144. package/dist/lib/schema/evaluator.d.ts +267 -0
  145. package/dist/lib/schema/evaluator.d.ts.map +1 -0
  146. package/dist/lib/schema/evaluator.js +169 -0
  147. package/dist/lib/schema/extend.d.ts +14 -0
  148. package/dist/lib/schema/extend.d.ts.map +1 -0
  149. package/dist/lib/schema/extend.js +51 -0
  150. package/dist/lib/schema/systemSchema.d.ts +112 -0
  151. package/dist/lib/schema/systemSchema.d.ts.map +1 -0
  152. package/dist/lib/schema/systemSchema.js +260 -0
  153. package/dist/lib/schema/typeGuards.d.ts +52 -0
  154. package/dist/lib/schema/typeGuards.d.ts.map +1 -0
  155. package/dist/lib/schema/typeGuards.js +127 -0
  156. package/dist/lib/schema/types.d.ts +156 -0
  157. package/dist/lib/schema/types.d.ts.map +1 -0
  158. package/dist/lib/schema/types.js +4 -0
  159. package/dist/lib/spanBuffer.d.ts +133 -0
  160. package/dist/lib/spanBuffer.d.ts.map +1 -0
  161. package/dist/lib/spanBuffer.js +442 -0
  162. package/dist/lib/spanBufferHelpers.d.ts +53 -0
  163. package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
  164. package/dist/lib/spanBufferHelpers.js +65 -0
  165. package/dist/lib/spanBufferStats.d.ts +38 -0
  166. package/dist/lib/spanBufferStats.d.ts.map +1 -0
  167. package/dist/lib/spanBufferStats.js +1 -0
  168. package/dist/lib/spanContext.d.ts +141 -0
  169. package/dist/lib/spanContext.d.ts.map +1 -0
  170. package/dist/lib/spanContext.js +763 -0
  171. package/dist/lib/sqlite/index.d.ts +14 -0
  172. package/dist/lib/sqlite/index.d.ts.map +1 -0
  173. package/dist/lib/sqlite/index.js +12 -0
  174. package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
  175. package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
  176. package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
  177. package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
  178. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
  179. package/dist/lib/sqlite/sqlite-common.js +207 -0
  180. package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
  181. package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
  182. package/dist/lib/sqlite/sqlite-d1.js +67 -0
  183. package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
  184. package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
  185. package/dist/lib/sqlite/sqlite-db.js +1 -0
  186. package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
  187. package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
  188. package/dist/lib/sqlite/sqlite-node.js +68 -0
  189. package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
  190. package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
  191. package/dist/lib/sqlite/sqlite-writer.js +78 -0
  192. package/dist/lib/testing/bun-harness.d.ts +150 -0
  193. package/dist/lib/testing/bun-harness.d.ts.map +1 -0
  194. package/dist/lib/testing/bun-harness.js +729 -0
  195. package/dist/lib/testing/extractFacts.d.ts +73 -0
  196. package/dist/lib/testing/extractFacts.d.ts.map +1 -0
  197. package/dist/lib/testing/extractFacts.js +237 -0
  198. package/dist/lib/testing/facts.d.ts +235 -0
  199. package/dist/lib/testing/facts.d.ts.map +1 -0
  200. package/dist/lib/testing/facts.js +209 -0
  201. package/dist/lib/testing/index.d.ts +58 -0
  202. package/dist/lib/testing/index.d.ts.map +1 -0
  203. package/dist/lib/testing/index.js +74 -0
  204. package/dist/lib/testing/queryable-span.d.ts +39 -0
  205. package/dist/lib/testing/queryable-span.d.ts.map +1 -0
  206. package/dist/lib/testing/queryable-span.js +58 -0
  207. package/dist/lib/testing/span-query.d.ts +21 -0
  208. package/dist/lib/testing/span-query.d.ts.map +1 -0
  209. package/dist/lib/testing/span-query.js +47 -0
  210. package/dist/lib/testing/stdio-replay.d.ts +4 -0
  211. package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
  212. package/dist/lib/testing/stdio-replay.js +42 -0
  213. package/dist/lib/testing/trace-query.d.ts +59 -0
  214. package/dist/lib/testing/trace-query.d.ts.map +1 -0
  215. package/dist/lib/testing/trace-query.js +462 -0
  216. package/dist/lib/testing/vitest-harness.d.ts +135 -0
  217. package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
  218. package/dist/lib/testing/vitest-harness.js +486 -0
  219. package/dist/lib/threadId.d.ts +58 -0
  220. package/dist/lib/threadId.d.ts.map +1 -0
  221. package/dist/lib/threadId.js +123 -0
  222. package/dist/lib/traceContext.d.ts +116 -0
  223. package/dist/lib/traceContext.d.ts.map +1 -0
  224. package/dist/lib/traceContext.js +37 -0
  225. package/dist/lib/traceId.d.ts +78 -0
  226. package/dist/lib/traceId.d.ts.map +1 -0
  227. package/dist/lib/traceId.js +87 -0
  228. package/dist/lib/traceRoot.d.ts +133 -0
  229. package/dist/lib/traceRoot.d.ts.map +1 -0
  230. package/dist/lib/traceRoot.es.d.ts +75 -0
  231. package/dist/lib/traceRoot.es.d.ts.map +1 -0
  232. package/dist/lib/traceRoot.es.js +129 -0
  233. package/dist/lib/traceRoot.js +19 -0
  234. package/dist/lib/traceRoot.node.d.ts +77 -0
  235. package/dist/lib/traceRoot.node.d.ts.map +1 -0
  236. package/dist/lib/traceRoot.node.js +133 -0
  237. package/dist/lib/traceRoot.universal.d.ts +3 -0
  238. package/dist/lib/traceRoot.universal.d.ts.map +1 -0
  239. package/dist/lib/traceRoot.universal.js +17 -0
  240. package/dist/lib/tracer.d.ts +296 -0
  241. package/dist/lib/tracer.d.ts.map +1 -0
  242. package/dist/lib/tracer.js +346 -0
  243. package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
  244. package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
  245. package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
  246. package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
  247. package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
  248. package/dist/lib/tracers/CompositeTracer.js +57 -0
  249. package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
  250. package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
  251. package/dist/lib/tracers/NoOpTracer.js +41 -0
  252. package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
  253. package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
  254. package/dist/lib/tracers/SQLiteTracer.js +84 -0
  255. package/dist/lib/tracers/StdioTracer.d.ts +83 -0
  256. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
  257. package/dist/lib/tracers/StdioTracer.js +270 -0
  258. package/dist/lib/tracers/TestTracer.d.ts +95 -0
  259. package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
  260. package/dist/lib/tracers/TestTracer.js +87 -0
  261. package/dist/lib/tracers/index.d.ts +12 -0
  262. package/dist/lib/tracers/index.d.ts.map +1 -0
  263. package/dist/lib/tracers/index.js +11 -0
  264. package/dist/lib/types.d.ts +366 -0
  265. package/dist/lib/types.d.ts.map +1 -0
  266. package/dist/lib/types.js +1 -0
  267. package/dist/lib/utf8Cache.d.ts +111 -0
  268. package/dist/lib/utf8Cache.d.ts.map +1 -0
  269. package/dist/lib/utf8Cache.js +177 -0
  270. package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
  271. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
  272. package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
  273. package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
  274. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
  275. package/dist/lib/wasm/wasmAllocator.js +227 -0
  276. package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
  277. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
  278. package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
  279. package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
  280. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
  281. package/dist/lib/wasm/wasmTraceRoot.js +264 -0
  282. package/dist/node.d.ts +7 -0
  283. package/dist/node.d.ts.map +1 -0
  284. package/dist/node.js +8 -0
  285. package/dist/testing.d.ts +18 -0
  286. package/dist/testing.d.ts.map +1 -0
  287. package/dist/testing.js +17 -0
  288. package/package.json +193 -0
  289. package/src/bun/preload.ts +11 -0
  290. package/src/bun/trace-preload.ts +14 -0
  291. package/src/es.ts +11 -0
  292. package/src/index.ts +194 -0
  293. package/src/lib/JsBufferStrategy.ts +102 -0
  294. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
  295. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
  296. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
  297. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
  298. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
  299. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
  300. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
  301. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
  302. package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
  303. package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
  304. package/src/lib/__tests__/binary-e2e.test.ts +203 -0
  305. package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
  306. package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
  307. package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
  308. package/src/lib/__tests__/effective-schema.test.ts +439 -0
  309. package/src/lib/__tests__/flechette.test.ts +42 -0
  310. package/src/lib/__tests__/flushScheduler.test.ts +537 -0
  311. package/src/lib/__tests__/integration.test.ts +600 -0
  312. package/src/lib/__tests__/library.test.ts +934 -0
  313. package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
  314. package/src/lib/__tests__/op-context-binding.test.ts +135 -0
  315. package/src/lib/__tests__/op-metadata.test.ts +198 -0
  316. package/src/lib/__tests__/op-type-safety.test.ts +71 -0
  317. package/src/lib/__tests__/package-exports.test.ts +57 -0
  318. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
  319. package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
  320. package/src/lib/__tests__/scope-attributes.test.ts +348 -0
  321. package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
  322. package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
  323. package/src/lib/__tests__/test-helpers.ts +318 -0
  324. package/src/lib/__tests__/timestamp.test.ts +259 -0
  325. package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
  326. package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
  327. package/src/lib/__tests__/tracer.test.ts +211 -0
  328. package/src/lib/__tests__/type-narrowing.test.ts +137 -0
  329. package/src/lib/archive/chunkCompaction.ts +44 -0
  330. package/src/lib/archive/chunkEnvelope.ts +79 -0
  331. package/src/lib/archive/chunkRouting.ts +70 -0
  332. package/src/lib/archive/chunkStats.ts +25 -0
  333. package/src/lib/archive/index.ts +4 -0
  334. package/src/lib/arrow/capacityStats.ts +340 -0
  335. package/src/lib/arrow/dictionaries.ts +159 -0
  336. package/src/lib/arrow/flechette.ts +114 -0
  337. package/src/lib/arrow/utils.ts +126 -0
  338. package/src/lib/buffer/Nanoseconds.ts +131 -0
  339. package/src/lib/bufferStrategy.ts +106 -0
  340. package/src/lib/capacityTuning.ts +102 -0
  341. package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
  342. package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
  343. package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
  344. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
  345. package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
  346. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
  347. package/src/lib/codegen/evaluatorGenerator.ts +309 -0
  348. package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
  349. package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
  350. package/src/lib/convertToArrow.ts +1805 -0
  351. package/src/lib/defineOpContext.ts +398 -0
  352. package/src/lib/errors/Blocked.ts +165 -0
  353. package/src/lib/errors/CodeError.ts +132 -0
  354. package/src/lib/errors/RetriesExhausted.ts +78 -0
  355. package/src/lib/errors/Transient.ts +168 -0
  356. package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
  357. package/src/lib/errors/__tests__/Transient.test.ts +129 -0
  358. package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
  359. package/src/lib/errors/index.ts +24 -0
  360. package/src/lib/errors/retry-policy.ts +87 -0
  361. package/src/lib/flushScheduler.ts +509 -0
  362. package/src/lib/library.ts +682 -0
  363. package/src/lib/logApi.ts +70 -0
  364. package/src/lib/logBinding.ts +67 -0
  365. package/src/lib/op.ts +103 -0
  366. package/src/lib/opContext/__tests__/retry.test.ts +764 -0
  367. package/src/lib/opContext/contextTypes.ts +130 -0
  368. package/src/lib/opContext/createOpGroup.ts +456 -0
  369. package/src/lib/opContext/defineOp.ts +281 -0
  370. package/src/lib/opContext/featureFlagTypes.ts +54 -0
  371. package/src/lib/opContext/index.ts +16 -0
  372. package/src/lib/opContext/opGroupTypes.ts +342 -0
  373. package/src/lib/opContext/opTypes.ts +80 -0
  374. package/src/lib/opContext/spanContextTypes.ts +398 -0
  375. package/src/lib/opContext/types.ts +403 -0
  376. package/src/lib/result.ts +550 -0
  377. package/src/lib/schema/LogSchema.ts +153 -0
  378. package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
  379. package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
  380. package/src/lib/schema/builder.ts +201 -0
  381. package/src/lib/schema/defineFeatureFlags.ts +91 -0
  382. package/src/lib/schema/defineLogSchema.ts +291 -0
  383. package/src/lib/schema/evaluator.ts +404 -0
  384. package/src/lib/schema/extend.ts +69 -0
  385. package/src/lib/schema/systemSchema.ts +339 -0
  386. package/src/lib/schema/typeGuards.ts +163 -0
  387. package/src/lib/schema/types.ts +265 -0
  388. package/src/lib/spanBuffer.ts +571 -0
  389. package/src/lib/spanBufferHelpers.ts +73 -0
  390. package/src/lib/spanBufferStats.ts +40 -0
  391. package/src/lib/spanContext.ts +1566 -0
  392. package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
  393. package/src/lib/sqlite/index.ts +26 -0
  394. package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
  395. package/src/lib/sqlite/sqlite-common.ts +309 -0
  396. package/src/lib/sqlite/sqlite-d1.ts +104 -0
  397. package/src/lib/sqlite/sqlite-db.ts +32 -0
  398. package/src/lib/sqlite/sqlite-node.ts +83 -0
  399. package/src/lib/sqlite/sqlite-writer.ts +128 -0
  400. package/src/lib/testing/TRACE-TESTING.md +100 -0
  401. package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
  402. package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
  403. package/src/lib/testing/__tests__/facts.test.ts +324 -0
  404. package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
  405. package/src/lib/testing/bun-harness.ts +990 -0
  406. package/src/lib/testing/extractFacts.ts +362 -0
  407. package/src/lib/testing/facts.ts +470 -0
  408. package/src/lib/testing/index.ts +141 -0
  409. package/src/lib/testing/queryable-span.ts +108 -0
  410. package/src/lib/testing/span-query.ts +65 -0
  411. package/src/lib/testing/stdio-replay.ts +50 -0
  412. package/src/lib/testing/trace-query.ts +329 -0
  413. package/src/lib/testing/vitest-harness.ts +691 -0
  414. package/src/lib/threadId.ts +135 -0
  415. package/src/lib/traceContext.ts +182 -0
  416. package/src/lib/traceId.ts +142 -0
  417. package/src/lib/traceRoot.es.ts +157 -0
  418. package/src/lib/traceRoot.node.ts +170 -0
  419. package/src/lib/traceRoot.ts +154 -0
  420. package/src/lib/traceRoot.universal.ts +22 -0
  421. package/src/lib/tracer.ts +896 -0
  422. package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
  423. package/src/lib/tracers/CompositeTracer.ts +76 -0
  424. package/src/lib/tracers/NoOpTracer.ts +73 -0
  425. package/src/lib/tracers/SQLiteTracer.ts +115 -0
  426. package/src/lib/tracers/StdioTracer.ts +380 -0
  427. package/src/lib/tracers/TestTracer.ts +146 -0
  428. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
  429. package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
  430. package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
  431. package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
  432. package/src/lib/tracers/index.ts +12 -0
  433. package/src/lib/types.ts +498 -0
  434. package/src/lib/utf8Cache.ts +201 -0
  435. package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
  436. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
  437. package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
  438. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
  439. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
  440. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
  441. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
  442. package/src/lib/wasm/allocator.zig +945 -0
  443. package/src/lib/wasm/wasmAllocator.ts +469 -0
  444. package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
  445. package/src/lib/wasm/wasmTraceRoot.ts +315 -0
  446. package/src/node.ts +10 -0
  447. package/src/testing.ts +18 -0
@@ -0,0 +1,647 @@
1
+ /**
2
+ * Arrow format correctness tests
3
+ *
4
+ * This test suite verifies that LMAO produces valid Arrow IPC format that can be:
5
+ * 1. Serialized to IPC binary format
6
+ * 2. Deserialized back to identical data
7
+ * 3. Read by any Arrow-compatible tool
8
+ *
9
+ * Per specs/lmao/01f_arrow_table_structure.md and 01b_columnar_buffer_architecture.md:
10
+ * - Zero-copy conversion MUST produce correct Arrow format
11
+ * - Dictionary encoding MUST work correctly
12
+ * - Null bitmaps MUST use Arrow format (1=valid, 0=null)
13
+ */
14
+
15
+ import { describe, expect, it } from 'bun:test';
16
+ import { dictionary, type Table, tableFromColumns, tableFromIPC, tableToIPC, uint8, utf8 } from '@uwdata/flechette';
17
+ import { convertToArrowTable } from '../../convertToArrow.js';
18
+ import { DEFAULT_METADATA } from '../../opContext/defineOp.js';
19
+ import { S } from '../../schema/builder.js';
20
+ import { ENTRY_TYPE_SPAN_START } from '../../schema/systemSchema.js';
21
+ import { createSpanBuffer } from '../../spanBuffer.js';
22
+ import { callBufferWriter, requireColumn } from '../arrow-test-helpers.js';
23
+
24
+ import { createTestSchema, createTestTraceRoot } from '../test-helpers.js';
25
+
26
+ /**
27
+ * Round-trip test: serialize to IPC, deserialize, verify data matches
28
+ */
29
+ const DICTIONARY_TYPE_ID = dictionary(utf8(), uint8()).typeId;
30
+
31
+ function verifyRoundTrip(table: Table, columnNames: string[]): Table {
32
+ const ipcColumns: Record<string, ReturnType<typeof getColumn>> = {};
33
+ for (const columnName of columnNames) {
34
+ const column = table.getChild(columnName);
35
+ if (!column) {
36
+ throw new Error(`Column not found for IPC round-trip: ${columnName}`);
37
+ }
38
+ ipcColumns[columnName] = column;
39
+ }
40
+
41
+ const ipcTable = tableFromColumns(ipcColumns);
42
+
43
+ // Serialize to IPC stream format
44
+ const ipcBytes = tableToIPC(ipcTable, { format: 'stream' });
45
+ if (!ipcBytes) {
46
+ throw new Error('Failed to serialize Arrow table');
47
+ }
48
+
49
+ // Deserialize back
50
+ const roundTripped = tableFromIPC(ipcBytes);
51
+
52
+ // Verify schema matches
53
+ expect(roundTripped.schema.fields.length).toBe(ipcTable.schema.fields.length);
54
+ for (let i = 0; i < ipcTable.schema.fields.length; i++) {
55
+ expect(roundTripped.schema.fields[i].name).toBe(ipcTable.schema.fields[i].name);
56
+ expect(roundTripped.schema.fields[i].type.typeId).toBe(ipcTable.schema.fields[i].type.typeId);
57
+ expect(roundTripped.schema.fields[i].nullable).toBe(ipcTable.schema.fields[i].nullable);
58
+ }
59
+
60
+ // Verify row count matches
61
+ expect(roundTripped.numRows).toBe(table.numRows);
62
+
63
+ return roundTripped;
64
+ }
65
+
66
+ function getColumn(table: Table, columnName: string) {
67
+ const column = table.getChild(columnName);
68
+ if (!column) {
69
+ throw new Error(`Column not found: ${columnName}`);
70
+ }
71
+ return column;
72
+ }
73
+
74
+ function getColumnValue(table: Table, columnName: string, rowIndex: number): unknown {
75
+ return getColumn(table, columnName).get(rowIndex);
76
+ }
77
+
78
+ function requireBigInt64Values(table: Table, columnName: string): BigInt64Array {
79
+ const column = requireColumn(table, columnName);
80
+ const batch = column.data[0];
81
+ if (!batch || !(batch.values instanceof BigInt64Array)) {
82
+ throw new Error(`Expected raw BigInt64Array values for column '${columnName}'`);
83
+ }
84
+ return batch.values;
85
+ }
86
+
87
+ function requireDictionaryLength(table: Table, columnName: string): number {
88
+ const column = requireColumn(table, columnName);
89
+ const batch = column.data[0];
90
+ const dictionary = batch ? Reflect.get(batch, 'dictionary') : undefined;
91
+ if (!(dictionary instanceof Object) || !('length' in dictionary) || typeof dictionary.length !== 'number') {
92
+ throw new Error(`Expected dictionary-encoded column '${columnName}'`);
93
+ }
94
+ return dictionary.length;
95
+ }
96
+
97
+ /**
98
+ * Set null bit at position (Arrow format: 1=valid, 0=null)
99
+ */
100
+ function setNull(nullBitmap: Uint8Array, idx: number, isNull: boolean): void {
101
+ const byteIndex = Math.floor(idx / 8);
102
+ const bitOffset = idx % 8;
103
+ if (isNull) {
104
+ nullBitmap[byteIndex] &= ~(1 << bitOffset);
105
+ } else {
106
+ nullBitmap[byteIndex] |= 1 << bitOffset;
107
+ }
108
+ }
109
+
110
+ describe('Arrow IPC Round-Trip', () => {
111
+ // No interners needed - direct string access is used
112
+
113
+ describe('serializes and deserializes correctly', () => {
114
+ it('number columns survive round-trip', () => {
115
+ const schema = createTestSchema({ value: S.number() });
116
+
117
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
118
+ buffer._opMetadata = DEFAULT_METADATA;
119
+
120
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
121
+
122
+ const testValues = [1.5, 2.5, 3.5, Number.NaN, 5.5];
123
+ for (const value of testValues) {
124
+ const idx = buffer._writeIndex;
125
+ buffer.timestamp[idx] = 1000n;
126
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
127
+ buffer.value(idx, value);
128
+ buffer._writeIndex++;
129
+ }
130
+
131
+ const table = convertToArrowTable(buffer);
132
+ const roundTripped = verifyRoundTrip(table, ['value']);
133
+
134
+ // Verify data values match
135
+ for (let i = 0; i < testValues.length; i++) {
136
+ const original = getColumnValue(table, 'value', i);
137
+ const restored = getColumnValue(roundTripped, 'value', i);
138
+
139
+ if (Number.isNaN(testValues[i])) {
140
+ expect(Number.isNaN(original)).toBe(true);
141
+ expect(Number.isNaN(restored)).toBe(true);
142
+ } else {
143
+ expect(restored).toBe(original);
144
+ expect(restored).toBe(testValues[i]);
145
+ }
146
+ }
147
+ });
148
+
149
+ it('boolean columns survive round-trip', () => {
150
+ const schema = createTestSchema({ flag: S.boolean() });
151
+
152
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 16);
153
+ buffer._opMetadata = DEFAULT_METADATA;
154
+
155
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
156
+
157
+ const testValues = [true, false, true, false, true, false, true, false, true];
158
+ for (const value of testValues) {
159
+ const idx = buffer._writeIndex;
160
+ buffer.timestamp[idx] = 1000n;
161
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
162
+ buffer.flag(idx, value);
163
+ buffer._writeIndex++;
164
+ }
165
+
166
+ const table = convertToArrowTable(buffer);
167
+ const roundTripped = verifyRoundTrip(table, ['flag']);
168
+
169
+ for (let i = 0; i < testValues.length; i++) {
170
+ expect(getColumnValue(roundTripped, 'flag', i)).toBe(testValues[i]);
171
+ }
172
+ });
173
+
174
+ it('enum columns survive round-trip', () => {
175
+ const schema = createTestSchema({ status: S.enum(['pending', 'active', 'completed'] as const) });
176
+
177
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
178
+ buffer._opMetadata = DEFAULT_METADATA;
179
+
180
+ // Write enum indices (0=pending, 1=active, 2=completed)
181
+ // Note: Buffer setters accept numeric indices for enum columns at runtime.
182
+ const testIndices = [0, 2, 1, 0, 2];
183
+ const expectedStrings = ['pending', 'completed', 'active', 'pending', 'completed'];
184
+ for (const enumIdx of testIndices) {
185
+ const idx = buffer._writeIndex;
186
+ buffer.timestamp[idx] = 1000n;
187
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
188
+ callBufferWriter(buffer, 'status', idx, enumIdx);
189
+ buffer._writeIndex++;
190
+ }
191
+
192
+ const table = convertToArrowTable(buffer);
193
+ for (let i = 0; i < expectedStrings.length; i++) {
194
+ expect(getColumnValue(table, 'status', i)).toBe(expectedStrings[i]);
195
+ }
196
+ });
197
+
198
+ it('category columns survive round-trip', () => {
199
+ const schema = createTestSchema({ userId: S.category() });
200
+
201
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
202
+ buffer._opMetadata = DEFAULT_METADATA;
203
+
204
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
205
+
206
+ const testValues = ['user-123', 'user-456', 'user-789', 'user-123', 'user-456'];
207
+ for (const userId of testValues) {
208
+ const idx = buffer._writeIndex;
209
+ buffer.timestamp[idx] = 1000n;
210
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
211
+ buffer.userId(idx, userId);
212
+ buffer._writeIndex++;
213
+ }
214
+
215
+ const table = convertToArrowTable(buffer);
216
+ const originalField = table.schema.fields.find((field) => field.name === 'userId');
217
+ expect(originalField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
218
+
219
+ for (let i = 0; i < testValues.length; i++) {
220
+ expect(getColumnValue(table, 'userId', i)).toBe(testValues[i]);
221
+ }
222
+ });
223
+
224
+ it('text columns survive round-trip', () => {
225
+ const schema = createTestSchema({ userMessage: S.text() });
226
+
227
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
228
+ buffer._opMetadata = DEFAULT_METADATA;
229
+
230
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
231
+
232
+ const testValues = ['First message', 'Second message', 'Third message', 'Second message', 'First message'];
233
+ for (const value of testValues) {
234
+ const idx = buffer._writeIndex;
235
+ buffer.timestamp[idx] = 1000n;
236
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
237
+ buffer.userMessage(idx, value);
238
+ buffer._writeIndex++;
239
+ }
240
+
241
+ const table = convertToArrowTable(buffer);
242
+
243
+ for (let i = 0; i < testValues.length; i++) {
244
+ expect(getColumnValue(table, 'userMessage', i)).toBe(testValues[i]);
245
+ }
246
+ });
247
+
248
+ it('nullable columns with nulls survive round-trip', () => {
249
+ const schema = createTestSchema({ value: S.number() });
250
+
251
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
252
+ buffer._opMetadata = DEFAULT_METADATA;
253
+
254
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
255
+
256
+ const testValues = [1.0, null, 3.0, null, 5.0];
257
+ for (const value of testValues) {
258
+ const idx = buffer._writeIndex;
259
+ buffer.timestamp[idx] = 1000n;
260
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
261
+ if (value !== null) {
262
+ buffer.value(idx, value);
263
+ } else {
264
+ // For null values, we need to explicitly mark as null in the bitmap
265
+ const nullBitmap = buffer.getNullsIfAllocated('value');
266
+ if (nullBitmap) {
267
+ setNull(nullBitmap, idx, true);
268
+ }
269
+ }
270
+ buffer._writeIndex++;
271
+ }
272
+
273
+ const table = convertToArrowTable(buffer);
274
+ const roundTripped = verifyRoundTrip(table, ['value']);
275
+
276
+ for (let i = 0; i < testValues.length; i++) {
277
+ expect(getColumnValue(roundTripped, 'value', i)).toBe(testValues[i]);
278
+ }
279
+ });
280
+
281
+ it('mixed column types survive round-trip', () => {
282
+ const schema = createTestSchema({
283
+ count: S.number(),
284
+ active: S.boolean(),
285
+ status: S.enum(['pending', 'active', 'completed'] as const),
286
+ userId: S.category(),
287
+ userMessage: S.text(),
288
+ });
289
+
290
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
291
+ buffer._opMetadata = DEFAULT_METADATA;
292
+
293
+ const testData = [
294
+ { count: 42, active: true, status: 0, userId: 'user-123', userMessage: 'First message' },
295
+ { count: 100, active: false, status: 1, userId: 'user-456', userMessage: 'Second message' },
296
+ { count: null, active: true, status: 2, userId: 'user-123', userMessage: 'First message' },
297
+ ];
298
+ for (const row of testData) {
299
+ const idx = buffer._writeIndex;
300
+ buffer.timestamp[idx] = 1000n;
301
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
302
+
303
+ if (row.count !== null) {
304
+ buffer.count(idx, row.count);
305
+ } else {
306
+ const nullBitmap = buffer.getNullsIfAllocated('count');
307
+ if (nullBitmap) {
308
+ setNull(nullBitmap, idx, true);
309
+ }
310
+ }
311
+ buffer.active(idx, row.active);
312
+ callBufferWriter(buffer, 'status', idx, row.status);
313
+ buffer.userId(idx, row.userId);
314
+ buffer.userMessage(idx, row.userMessage);
315
+ buffer._writeIndex++;
316
+ }
317
+
318
+ const table = convertToArrowTable(buffer);
319
+ const roundTripped = verifyRoundTrip(table, ['count', 'active']);
320
+
321
+ // Verify first row
322
+ expect(getColumnValue(roundTripped, 'count', 0)).toBe(42);
323
+ expect(getColumnValue(roundTripped, 'active', 0)).toBe(true);
324
+ expect(getColumnValue(table, 'status', 0)).toBe('pending');
325
+ expect(getColumnValue(table, 'userId', 0)).toBe('user-123');
326
+ expect(getColumnValue(table, 'userMessage', 0)).toBe('First message');
327
+
328
+ // Verify second row
329
+ expect(getColumnValue(roundTripped, 'count', 1)).toBe(100);
330
+ expect(getColumnValue(roundTripped, 'active', 1)).toBe(false);
331
+ expect(getColumnValue(table, 'status', 1)).toBe('active');
332
+ expect(getColumnValue(table, 'userId', 1)).toBe('user-456');
333
+ expect(getColumnValue(table, 'userMessage', 1)).toBe('Second message');
334
+
335
+ // Verify third row with null
336
+ expect(getColumnValue(roundTripped, 'count', 2)).toBeNull();
337
+ expect(getColumnValue(roundTripped, 'active', 2)).toBe(true);
338
+ expect(getColumnValue(table, 'status', 2)).toBe('completed');
339
+ expect(getColumnValue(table, 'userId', 2)).toBe('user-123');
340
+ expect(getColumnValue(table, 'userMessage', 2)).toBe('First message');
341
+ });
342
+
343
+ it('system columns survive round-trip', () => {
344
+ const schema = createTestSchema({});
345
+
346
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
347
+ buffer._opMetadata = DEFAULT_METADATA;
348
+
349
+ // Write a few rows with timestamps (BigInt64Array stores nanoseconds)
350
+ const timestamps = [1000n, 1100n, 1200n];
351
+ for (let i = 0; i < 3; i++) {
352
+ const idx = buffer._writeIndex;
353
+ buffer.timestamp[idx] = timestamps[i];
354
+ buffer.entry_type[idx] = i;
355
+ buffer._writeIndex++;
356
+ }
357
+
358
+ const table = convertToArrowTable(buffer);
359
+ const roundTripped = verifyRoundTrip(table, [
360
+ 'timestamp',
361
+ 'thread_id',
362
+ 'span_id',
363
+ 'parent_thread_id',
364
+ 'parent_span_id',
365
+ ]);
366
+
367
+ // Verify system columns exist in source table
368
+ const sourceFieldNames = table.schema.fields.map((f) => f.name);
369
+ expect(sourceFieldNames).toContain('timestamp');
370
+ expect(sourceFieldNames).toContain('trace_id');
371
+ expect(sourceFieldNames).toContain('thread_id');
372
+ expect(sourceFieldNames).toContain('span_id');
373
+ expect(sourceFieldNames).toContain('parent_thread_id');
374
+ expect(sourceFieldNames).toContain('parent_span_id');
375
+ expect(sourceFieldNames).toContain('entry_type');
376
+ expect(sourceFieldNames).toContain('package_name');
377
+ expect(sourceFieldNames).toContain('package_file');
378
+
379
+ // Verify IPC round-tripped subset columns exist
380
+ const fieldNames = roundTripped.schema.fields.map((f) => f.name);
381
+ expect(fieldNames).toContain('timestamp');
382
+ expect(fieldNames).toContain('thread_id');
383
+ expect(fieldNames).toContain('span_id');
384
+ expect(fieldNames).toContain('parent_thread_id');
385
+ expect(fieldNames).toContain('parent_span_id');
386
+
387
+ // Verify timestamps round-tripped correctly
388
+ // Arrow's getter converts nanoseconds to a decimal, so access raw BigInt64Array
389
+ const timestampIndex = roundTripped.schema.fields.findIndex((f) => f.name === 'timestamp');
390
+ const timestampVector = roundTripped.getChildAt(timestampIndex);
391
+ if (!timestampVector) {
392
+ throw new Error('Timestamp vector not found');
393
+ }
394
+ const rawTimestamps = requireBigInt64Values(roundTripped, 'timestamp');
395
+ for (let i = 0; i < 3; i++) {
396
+ expect(rawTimestamps[i]).toBe(timestamps[i]);
397
+ }
398
+ });
399
+ });
400
+
401
+ describe('schema correctness', () => {
402
+ it('system columns have correct nullability', () => {
403
+ const schema = createTestSchema({ userAttr: S.number() });
404
+
405
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
406
+ buffer._opMetadata = DEFAULT_METADATA;
407
+
408
+ const idx = buffer._writeIndex;
409
+ buffer.timestamp[idx] = 1000n;
410
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
411
+ buffer._writeIndex++;
412
+
413
+ const table = convertToArrowTable(buffer);
414
+
415
+ // System columns must be present and match current conversion contract.
416
+ const expectedSystemColumns = [
417
+ 'timestamp',
418
+ 'trace_id',
419
+ 'thread_id',
420
+ 'span_id',
421
+ 'entry_type',
422
+ 'package_name',
423
+ 'package_file',
424
+ ];
425
+ for (const colName of expectedSystemColumns) {
426
+ const field = table.schema.fields.find((f) => f.name === colName);
427
+ expect(field).toBeDefined();
428
+ expect(field?.nullable).toBe(true);
429
+ }
430
+
431
+ // Columns that SHOULD be nullable
432
+ const nullableColumns = ['parent_thread_id', 'parent_span_id', 'userAttr'];
433
+ for (const colName of nullableColumns) {
434
+ const field = table.schema.fields.find((f) => f.name === colName);
435
+ expect(field).toBeDefined();
436
+ expect(field?.nullable).toBe(true);
437
+ }
438
+ });
439
+
440
+ it('dictionary columns have correct type', () => {
441
+ const schema = createTestSchema({
442
+ category: S.category(),
443
+ text: S.text(),
444
+ status: S.enum(['a', 'b'] as const),
445
+ });
446
+
447
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
448
+ buffer._opMetadata = DEFAULT_METADATA;
449
+
450
+ const idx = buffer._writeIndex;
451
+ buffer.timestamp[idx] = 1000n;
452
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
453
+ buffer.category(idx, 'cat1');
454
+ buffer.text(idx, 'text1');
455
+ callBufferWriter(buffer, 'status', idx, 0);
456
+ buffer._writeIndex++;
457
+
458
+ const table = convertToArrowTable(buffer);
459
+
460
+ // Category and text should be Dictionary<Utf8, Uint32>
461
+ const categoryField = table.schema.fields.find((f) => f.name === 'category');
462
+ expect(categoryField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
463
+
464
+ const textField = table.schema.fields.find((f) => f.name === 'text');
465
+ expect(textField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
466
+
467
+ // Enum should be Dictionary<Utf8, Uint8>
468
+ const enumField = table.schema.fields.find((f) => f.name === 'status');
469
+ expect(enumField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
470
+ });
471
+ });
472
+
473
+ describe('null bitmap format', () => {
474
+ it('uses Arrow format (1=valid, 0=null)', () => {
475
+ const schema = createTestSchema({ value: S.number() });
476
+
477
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
478
+ buffer._opMetadata = DEFAULT_METADATA;
479
+
480
+ // Write pattern: valid, null, valid, null, valid, null, valid, null
481
+ const values = [1.0, null, 2.0, null, 3.0, null, 4.0, null];
482
+ for (const value of values) {
483
+ const idx = buffer._writeIndex;
484
+ buffer.timestamp[idx] = 1000n;
485
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
486
+ if (value !== null) {
487
+ buffer.value(idx, value);
488
+ } else {
489
+ const nullBitmap = buffer.getNullsIfAllocated('value');
490
+ if (nullBitmap) {
491
+ setNull(nullBitmap, idx, true);
492
+ }
493
+ }
494
+ buffer._writeIndex++;
495
+ }
496
+
497
+ const table = convertToArrowTable(buffer);
498
+
499
+ // Extract value column
500
+ const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
501
+ const valueVector = table.getChildAt(valueColumnIndex);
502
+ if (!valueVector) {
503
+ throw new Error('Value vector not found');
504
+ }
505
+ const valueData = valueVector.data[0] as { nullCount: number; nullBitmap?: Uint8Array; validity?: Uint8Array };
506
+
507
+ // Verify null count
508
+ expect(valueData.nullCount).toBe(4);
509
+
510
+ // Verify null bitmap (1=valid, 0=null)
511
+ // Pattern: 01010101 = 0x55
512
+ const nullBitmap = valueData.nullBitmap ?? valueData.validity;
513
+ expect(nullBitmap).toBeDefined();
514
+ expect(nullBitmap?.[0]).toBe(0b01010101);
515
+ });
516
+
517
+ it('handles sparse nulls correctly', () => {
518
+ const schema = createTestSchema({ value: S.number() });
519
+
520
+ // Need capacity for 10 values
521
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 16);
522
+ buffer._opMetadata = DEFAULT_METADATA;
523
+
524
+ // Only one null in 10 values
525
+ const values = [1, 2, 3, null, 5, 6, 7, 8, 9, 10];
526
+ for (const value of values) {
527
+ const idx = buffer._writeIndex;
528
+ buffer.timestamp[idx] = 1000n;
529
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
530
+ if (value !== null) {
531
+ buffer.value(idx, value);
532
+ } else {
533
+ const nullBitmap = buffer.getNullsIfAllocated('value');
534
+ if (nullBitmap) {
535
+ setNull(nullBitmap, idx, true);
536
+ }
537
+ }
538
+ buffer._writeIndex++;
539
+ }
540
+
541
+ const table = convertToArrowTable(buffer);
542
+
543
+ const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
544
+ const valueVector = table.getChildAt(valueColumnIndex);
545
+ if (!valueVector) {
546
+ throw new Error('Value vector not found');
547
+ }
548
+ const valueData = valueVector.data[0];
549
+
550
+ expect(valueData.nullCount).toBe(1);
551
+
552
+ // Verify all values round-trip correctly
553
+ for (let i = 0; i < values.length; i++) {
554
+ expect(getColumnValue(table, 'value', i)).toBe(values[i]);
555
+ }
556
+ });
557
+
558
+ it('omits null bitmap when no nulls', () => {
559
+ const schema = createTestSchema({ value: S.number() });
560
+
561
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
562
+ buffer._opMetadata = DEFAULT_METADATA;
563
+
564
+ // No nulls - write all valid values
565
+ const values = [1, 2, 3, 4, 5];
566
+ for (const value of values) {
567
+ const idx = buffer._writeIndex;
568
+ buffer.timestamp[idx] = 1000n;
569
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
570
+ buffer.value(idx, value);
571
+ buffer._writeIndex++;
572
+ }
573
+
574
+ const table = convertToArrowTable(buffer);
575
+
576
+ const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
577
+ const valueVector = table.getChildAt(valueColumnIndex);
578
+ if (!valueVector) {
579
+ throw new Error('Value vector not found');
580
+ }
581
+ const valueData = valueVector.data[0];
582
+
583
+ expect(valueData.nullCount).toBe(0);
584
+ // When nullCount is 0, Arrow may or may not include a bitmap
585
+ // The important thing is nullCount is correct
586
+ });
587
+ });
588
+
589
+ describe('dictionary encoding', () => {
590
+ it('preserves dictionary values through round-trip', () => {
591
+ const schema = createTestSchema({ category: S.category() });
592
+
593
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
594
+ buffer._opMetadata = DEFAULT_METADATA;
595
+
596
+ // Write a fewbuffer._opMetadata = DEFAULT_METADATA;
597
+
598
+ const testValues = ['alpha', 'beta', 'zebra', 'alpha', 'beta'];
599
+ for (const category of testValues) {
600
+ const idx = buffer._writeIndex;
601
+ buffer.timestamp[idx] = 1000n;
602
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
603
+ buffer.category(idx, category);
604
+ buffer._writeIndex++;
605
+ }
606
+
607
+ const table = convertToArrowTable(buffer);
608
+ for (let i = 0; i < testValues.length; i++) {
609
+ expect(getColumnValue(table, 'category', i)).toBe(testValues[i]);
610
+ }
611
+ });
612
+
613
+ it('handles repeated values efficiently', () => {
614
+ const schema = createTestSchema({ userId: S.category() });
615
+
616
+ // Use capacity of 128 to hold 100 rows without overflow
617
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 128);
618
+ buffer._opMetadata = DEFAULT_METADATA;
619
+
620
+ // Write same value many times
621
+ const testValue = 'user-repeated';
622
+ for (let i = 0; i < 100; i++) {
623
+ const idx = buffer._writeIndex;
624
+ buffer.timestamp[idx] = 1000n;
625
+ buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
626
+ buffer.userId(idx, testValue);
627
+ buffer._writeIndex++;
628
+ }
629
+
630
+ const table = convertToArrowTable(buffer);
631
+
632
+ // Verify all 100 rows have the same value by accessing the column directly
633
+ const userIdIndex = table.schema.fields.findIndex((f) => f.name === 'userId');
634
+ const userIdVector = table.getChildAt(userIdIndex);
635
+ if (!userIdVector) {
636
+ throw new Error('UserId vector not found');
637
+ }
638
+
639
+ for (let i = 0; i < 100; i++) {
640
+ expect(userIdVector.get(i)).toBe(testValue);
641
+ }
642
+
643
+ // Dictionary should only have 1 unique value
644
+ expect(requireDictionaryLength(table, 'userId')).toBe(1);
645
+ });
646
+ });
647
+ });