@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,83 @@
1
+ /// <reference types="node" />
2
+
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ import type {
5
+ AsyncSQLiteDatabase,
6
+ AsyncSQLiteStatement,
7
+ SyncSQLiteDatabase,
8
+ SyncSQLiteStatement,
9
+ } from './sqlite-db.js';
10
+
11
+ function toSyncStatement(statement: {
12
+ run(...params: unknown[]): unknown;
13
+ all(...params: unknown[]): unknown[];
14
+ get(...params: unknown[]): unknown;
15
+ }): SyncSQLiteStatement {
16
+ return {
17
+ run(...params: unknown[]): void {
18
+ statement.run(...params);
19
+ },
20
+ all(...params: unknown[]): unknown[] {
21
+ return statement.all(...params);
22
+ },
23
+ get(...params: unknown[]): unknown {
24
+ return statement.get(...params);
25
+ },
26
+ };
27
+ }
28
+
29
+ /**
30
+ * Create a Node built-in sqlite database adapter.
31
+ *
32
+ * Use this in Node Vitest setup when you want trace output persisted
33
+ * to a deterministic file path.
34
+ */
35
+ export function createNodeSQLiteDatabase(dbPath: string): SyncSQLiteDatabase {
36
+ const db = new DatabaseSync(dbPath);
37
+ return {
38
+ exec(sql: string): void {
39
+ db.exec(sql);
40
+ },
41
+ prepare(sql: string): SyncSQLiteStatement {
42
+ return toSyncStatement(db.prepare(sql));
43
+ },
44
+ close(): void {
45
+ db.close();
46
+ },
47
+ };
48
+ }
49
+
50
+ function toAsyncStatement(statement: SyncSQLiteStatement): AsyncSQLiteStatement {
51
+ return {
52
+ async run(...params: unknown[]): Promise<void> {
53
+ statement.run(...params);
54
+ },
55
+ async all(...params: unknown[]): Promise<unknown[]> {
56
+ return statement.all(...params);
57
+ },
58
+ async get(...params: unknown[]): Promise<unknown> {
59
+ return statement.get(...params);
60
+ },
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Create an async adapter around Node built-in sqlite.
66
+ *
67
+ * Useful when wiring into `createAsyncDatabase` callbacks while still
68
+ * writing to a deterministic file path on Node.
69
+ */
70
+ export function createNodeSQLiteAsyncDatabase(dbPath: string): AsyncSQLiteDatabase {
71
+ const syncDb = createNodeSQLiteDatabase(dbPath);
72
+ return {
73
+ async exec(sql: string): Promise<void> {
74
+ syncDb.exec(sql);
75
+ },
76
+ prepare(sql: string): AsyncSQLiteStatement {
77
+ return toAsyncStatement(syncDb.prepare(sql));
78
+ },
79
+ async close(): Promise<void> {
80
+ syncDb.close();
81
+ },
82
+ };
83
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * SQLiteTraceWriter - General-purpose writer that persists span buffer trees to SQLite.
3
+ *
4
+ * Accepts a SyncSQLiteDatabase instance (from bun:sqlite or better-sqlite3)
5
+ * and persists the full span tree as a flat `spans` table with dynamic column
6
+ * evolution based on the LogSchema fields found at flush time.
7
+ *
8
+ * Architecture:
9
+ * - Single `spans` table — no runs/log_entries decomposition
10
+ * - trace_id IS the run identifier (one root span per trace)
11
+ * - Tree structure via span_id / parent_span_id (no depth column)
12
+ * - User schema columns added dynamically via ALTER TABLE
13
+ * - Per-buffer ensureColumns for cross-library schema merging
14
+ *
15
+ * @module sqlite-writer
16
+ */
17
+
18
+ import type { LogSchema } from '../schema/LogSchema.js';
19
+ import type { AnySpanBuffer } from '../types.js';
20
+ import {
21
+ buildAddColumnSql,
22
+ buildInsertParams,
23
+ buildInsertSql,
24
+ extractSqliteColumnsFromTableInfo,
25
+ getActiveUserFields,
26
+ getInsertStatementCacheKey,
27
+ getMissingSchemaColumns,
28
+ isSqliteDuplicateColumnError,
29
+ parseSqliteTableInfoRows,
30
+ SPANS_TABLE_INFO_SQL,
31
+ SPANS_TABLE_INIT_SQL,
32
+ type SpanSegment,
33
+ walkSpanSegments,
34
+ } from './sqlite-common.js';
35
+ import type { SyncSQLiteDatabase, SyncSQLiteStatement } from './sqlite-db.js';
36
+
37
+ export interface SQLiteWriterConfig {
38
+ /** Path to SQLite file. Default: '.trace-results.db' */
39
+ dbPath?: string;
40
+ }
41
+
42
+ export class SQLiteTraceWriter {
43
+ private knownColumns = new Set<string>();
44
+ private insertStmtCache = new Map<string, SyncSQLiteStatement>();
45
+
46
+ constructor(private db: SyncSQLiteDatabase) {
47
+ this.init();
48
+ }
49
+
50
+ private init(): void {
51
+ // Parallel Bun test workers share one trace DB, so wait for short SQLite writer locks instead of failing setup.
52
+ this.db.exec('PRAGMA busy_timeout = 10000');
53
+ this.db.exec(SPANS_TABLE_INIT_SQL);
54
+
55
+ this.refreshKnownColumns();
56
+ }
57
+
58
+ private refreshKnownColumns(): void {
59
+ this.knownColumns.clear();
60
+ // WHY: PRAGMA row shape changes would make later ALTER/INSERT logic drift silently, so validate here before
61
+ // mutating the writer's cached schema view.
62
+ const rows = parseSqliteTableInfoRows(this.db.prepare(SPANS_TABLE_INFO_SQL).all());
63
+ for (const column of extractSqliteColumnsFromTableInfo(rows)) {
64
+ this.knownColumns.add(column.name);
65
+ }
66
+ }
67
+
68
+ /** Ensure user-defined schema columns exist in the spans table */
69
+ private ensureColumns(schema: LogSchema): void {
70
+ for (const column of getMissingSchemaColumns(schema, this.knownColumns)) {
71
+ try {
72
+ this.db.exec(buildAddColumnSql(column));
73
+ } catch (error) {
74
+ if (!isSqliteDuplicateColumnError(error, column.name)) {
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ this.refreshKnownColumns();
80
+ this.knownColumns.add(column.name);
81
+ }
82
+ }
83
+
84
+ private writeSegmentRows(segment: SpanSegment): void {
85
+ this.ensureColumns(segment.buffer._logSchema);
86
+
87
+ const activeUserFields = getActiveUserFields(segment.buffer._logSchema, this.knownColumns);
88
+ const insertStmt = this.getInsertStatement(activeUserFields);
89
+
90
+ for (let row = 0; row < segment.buffer._writeIndex; row++) {
91
+ insertStmt.run(...buildInsertParams(segment, row, activeUserFields));
92
+ }
93
+ }
94
+
95
+ private flushAllSegments(rootBuffer: AnySpanBuffer): void {
96
+ for (const segment of walkSpanSegments(rootBuffer)) {
97
+ this.writeSegmentRows(segment);
98
+ }
99
+ }
100
+
101
+ private getInsertStatement(activeUserFields: readonly string[]): SyncSQLiteStatement {
102
+ const key = getInsertStatementCacheKey(activeUserFields);
103
+ const cached = this.insertStmtCache.get(key);
104
+ if (cached) {
105
+ return cached;
106
+ }
107
+
108
+ const stmt = this.db.prepare(buildInsertSql(activeUserFields));
109
+ this.insertStmtCache.set(key, stmt);
110
+ return stmt;
111
+ }
112
+
113
+ /** Write a root SpanBuffer tree to the database */
114
+ flush(rootBuffer: AnySpanBuffer): void {
115
+ this.db.exec('BEGIN IMMEDIATE');
116
+ try {
117
+ this.flushAllSegments(rootBuffer);
118
+ this.db.exec('COMMIT');
119
+ } catch (error) {
120
+ this.db.exec('ROLLBACK');
121
+ throw error;
122
+ }
123
+ }
124
+
125
+ close(): void {
126
+ this.db.close();
127
+ }
128
+ }
@@ -0,0 +1,100 @@
1
+ # Trace-Testing with LMAO
2
+
3
+ > Based on Akkartik's "tracing tests": https://akkartik.name/post/tracing-tests
4
+
5
+ ## Core Principle
6
+
7
+ **Test WHAT happened (domain facts), not HOW (implementation details).**
8
+
9
+ Traditional tests couple to internal structure:
10
+
11
+ ```typescript
12
+ const result = await myOp(args);
13
+ expect(result.status).toBe('success'); // Brittle - breaks on refactor
14
+ ```
15
+
16
+ Trace-tests assert on facts emitted during execution:
17
+
18
+ ```typescript
19
+ await trace('my-op', myOp);
20
+ expect(facts.has(spanOk('my-op'))).toBe(true); // Robust - survives refactoring
21
+ ```
22
+
23
+ ## LMAO Fact Types
24
+
25
+ Facts are strongly-typed template literals. Invalid facts = compile errors.
26
+
27
+ | Type | Format | Example |
28
+ | ----------- | ------------------------ | -------------------------- |
29
+ | `SpanFact` | `span:${name}: ${state}` | `span:fetch-user: ok` |
30
+ | `LogFact` | `log:${level}: ${msg}` | `log:info: Processing` |
31
+ | `TagFact` | `tag:${key}: ${value}` | `tag:userId: 123` |
32
+ | `ScopeFact` | `scope:${key}: ${value}` | `scope:requestId: req-abc` |
33
+ | `FFFact` | `ff:${flag}: ${value}` | `ff:darkMode: true` |
34
+
35
+ Span states: `started`, `ok`, `err(CODE)`, `exception(msg)`
36
+
37
+ ## Usage
38
+
39
+ ```typescript
40
+ import { TestTracer, defineOpContext } from '@smoothbricks/lmao';
41
+ import { extractFacts, spanStarted, spanOk, spanErr, tagFact, logInfo } from '@smoothbricks/lmao/testing';
42
+
43
+ // 1. Run traced code
44
+ const tracer = new TestTracer(opContext);
45
+ await tracer.trace('process-order', async (ctx) => {
46
+ ctx.tag.orderId('ord-123');
47
+ await ctx.span('validate', async (c) => c.ok(null));
48
+ await ctx.span('charge', async (c) => c.ok(null));
49
+ return ctx.ok('done');
50
+ });
51
+
52
+ // 2. Extract facts from buffer tree
53
+ const facts = extractFacts(tracer.rootBuffers[0]);
54
+
55
+ // 3. Assert on WHAT happened
56
+ expect(facts.has(spanOk('process-order'))).toBe(true);
57
+ expect(facts.has(tagFact('orderId', 'ord-123'))).toBe(true);
58
+ expect(facts.hasInOrder([spanStarted('validate'), spanOk('validate'), spanStarted('charge'), spanOk('charge')])).toBe(
59
+ true
60
+ );
61
+ expect(facts.hasMatch('span:*: err(*)')).toBe(false);
62
+ ```
63
+
64
+ ## FactArray API
65
+
66
+ | Method | Purpose |
67
+ | ------------------------------- | -------------------------------------- |
68
+ | `has(fact)` | Exact match |
69
+ | `hasMatch(pattern)` | Glob match (`*` = any non-colon chars) |
70
+ | `hasInOrder([...])` | Facts appear in order (not adjacent) |
71
+ | `byNamespace('span')` | Filter to namespace |
72
+ | `spans()` / `logs()` / `tags()` | Typed filters |
73
+ | `match(pattern)` | Return matching facts |
74
+
75
+ ## Buffer Layout (Why This Works)
76
+
77
+ Per `specs/lmao/01h_entry_types_and_logging_primitives.md`:
78
+
79
+ - **Row 0**: `span-start` + tag writes (`ctx.tag.*` overwrites here)
80
+ - **Row 1**: Completion (`span-ok`/`span-err`/`span-exception`)
81
+ - **Row 2+**: Log entries (`ctx.log.*` appends here)
82
+
83
+ `extractFacts()` walks the buffer tree depth-first, emitting facts in execution order.
84
+
85
+ ## When to Use Trace-Testing
86
+
87
+ ✅ **Use for**: Operation ordering, error handling, tag/scope propagation, multi-span workflows ❌ **Don't use for**:
88
+ Return value validation, performance benchmarks, schema validation
89
+
90
+ ## Key Insight
91
+
92
+ > "Tests no longer need call fine-grained helpers directly... The trace checks that the program correctly computed a
93
+ > specific _fact_, while remaining oblivious about _how_ it was computed." — Akkartik
94
+
95
+ This makes tests resilient to:
96
+
97
+ - Function boundary changes
98
+ - Sync → async refactoring
99
+ - Internal restructuring
100
+ - Adding/removing intermediate steps
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { defineOpContext } from '../../defineOpContext.js';
3
+ import { S } from '../../schema/builder.js';
4
+ import { defineLogSchema } from '../../schema/defineLogSchema.js';
5
+ import { TestTracer } from '../../tracers/TestTracer.js';
6
+ import { type BunTestModuleShape, makeBunTestSuiteTracer, makeTestTracer } from '../bun-harness.js';
7
+
8
+ type BunTestModuleLike = BunTestModuleShape;
9
+
10
+ function createImmediateTestFn(): BunTestModuleLike['it'] {
11
+ const runBase = (_name: string, fn: () => unknown | Promise<unknown>) => fn();
12
+ return Object.assign(runBase, it, {
13
+ only: runBase,
14
+ skipIf: (condition: boolean) => (condition ? it.skip : runBase),
15
+ if: (condition: boolean) => (condition ? runBase : it.skip),
16
+ });
17
+ }
18
+
19
+ function createImmediateDescribeFn(): BunTestModuleLike['describe'] {
20
+ const runBase = (_name: string, fn: () => void) => fn();
21
+ return Object.assign(runBase, describe, {
22
+ only: runBase,
23
+ skipIf: (condition: boolean) => (condition ? describe.skip : runBase),
24
+ if: (condition: boolean) => (condition ? runBase : describe.skip),
25
+ });
26
+ }
27
+
28
+ function createImmediateIt() {
29
+ return createImmediateTestFn();
30
+ }
31
+
32
+ function createImmediateDescribe() {
33
+ return createImmediateDescribeFn();
34
+ }
35
+
36
+ function createImmediateBunTestModule(): BunTestModuleLike {
37
+ const itFn = createImmediateIt();
38
+ return {
39
+ it: itFn,
40
+ describe: createImmediateDescribe(),
41
+ test: itFn,
42
+ };
43
+ }
44
+
45
+ const baseBinding = defineOpContext({
46
+ logSchema: defineLogSchema({ base_field: S.category() }),
47
+ });
48
+
49
+ const suiteWithExtension = makeBunTestSuiteTracer(baseBinding, {
50
+ extraTestColumns: {
51
+ test_metric: S.number(),
52
+ },
53
+ });
54
+
55
+ type ExtendedSpan = ReturnType<typeof suiteWithExtension.useTestSpan>;
56
+ type HasExtendedTag = ExtendedSpan['tag'] extends { test_metric: (value: number) => unknown } ? true : false;
57
+ type HasExtendedLog =
58
+ ReturnType<ExtendedSpan['log']['info']> extends { test_metric: (value: number) => unknown } ? true : false;
59
+ const hasExtendedTag: HasExtendedTag = true;
60
+ const hasExtendedLog: HasExtendedLog = true;
61
+
62
+ describe('bun harness test log schema extension', () => {
63
+ it('includes extension fields in suite span typing', () => {
64
+ expect(hasExtendedTag).toBe(true);
65
+ expect(hasExtendedLog).toBe(true);
66
+ });
67
+
68
+ it('writes extension fields through tag and log APIs', async () => {
69
+ const tracer = makeTestTracer(baseBinding, {
70
+ extraTestColumns: {
71
+ test_metric: S.number(),
72
+ test_note: S.text(),
73
+ },
74
+ });
75
+ tracer.setup();
76
+
77
+ const wrappedModule = tracer.createBunTestMock(createImmediateBunTestModule());
78
+ await wrappedModule.it('writes test-only fields', async () => {
79
+ const span = tracer.useTestSpan();
80
+ span.tag.test_metric(123);
81
+ span.log.info('row-1').test_metric(456).test_note('hello');
82
+
83
+ const buffer = span.buffer;
84
+ expect(buffer.test_metric_values[0]).toBe(123);
85
+ expect(buffer.test_metric_values[2]).toBe(456);
86
+ expect(buffer.test_note_values[2]).toBe('hello');
87
+ });
88
+ });
89
+
90
+ it('defaults to an in-memory TestTracer when sqlite and verbose are off', () => {
91
+ const tracer = makeTestTracer(baseBinding);
92
+ tracer.setup();
93
+
94
+ expect(tracer.getTracer()).toBeInstanceOf(TestTracer);
95
+ });
96
+
97
+ it('rejects duplicate extra test columns instead of silently erasing them', () => {
98
+ const tracer = makeTestTracer(baseBinding, {
99
+ extraTestColumns: {
100
+ base_field: S.category(),
101
+ },
102
+ });
103
+
104
+ expect(() => tracer.setup()).toThrow(
105
+ "Test harness schema column 'base_field' already exists in the bound log schema",
106
+ );
107
+ });
108
+ });
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Tests for extractFacts - the bridge between buffers and facts.
3
+ */
4
+
5
+ import { describe, expect, it } from 'bun:test';
6
+ import { createTestTracerOptions } from '../../__tests__/test-helpers.js';
7
+ import { defineOpContext } from '../../defineOpContext.js';
8
+ import { defineCodeError } from '../../result.js';
9
+ import { S } from '../../schema/builder.js';
10
+ import { defineFeatureFlags } from '../../schema/defineFeatureFlags.js';
11
+ import { defineLogSchema } from '../../schema/defineLogSchema.js';
12
+ import { InMemoryFlagEvaluator } from '../../schema/evaluator.js';
13
+ import { TestTracer } from '../../tracers/TestTracer.js';
14
+ import { extractFacts } from '../extractFacts.js';
15
+ import { ffFact, logInfo, logWarn, spanErr, spanOk, spanStarted, tagFact } from '../facts.js';
16
+
17
+ // Define a test error for ctx.err tests
18
+ const NOT_FOUND = defineCodeError('NOT_FOUND')<{ detail: string }>();
19
+
20
+ describe('extractFacts', () => {
21
+ // Create a test schema
22
+ const testSchema = defineLogSchema({
23
+ userId: S.category(),
24
+ orderId: S.category(),
25
+ amount: S.number(),
26
+ });
27
+
28
+ const opContext = defineOpContext({ logSchema: testSchema });
29
+ const featureFlags = defineFeatureFlags({
30
+ advancedValidation: S.boolean().default(false).sync(),
31
+ });
32
+ const opContextWithFlags = defineOpContext({
33
+ logSchema: testSchema,
34
+ flags: featureFlags.schema,
35
+ });
36
+ const flagEvaluator = new InMemoryFlagEvaluator(featureFlags.schema, {
37
+ advancedValidation: true,
38
+ });
39
+
40
+ it('extracts span lifecycle facts from a simple trace', async () => {
41
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
42
+
43
+ await tracer.trace('my-operation', async (ctx) => {
44
+ return ctx.ok('done');
45
+ });
46
+
47
+ expect(tracer.rootBuffers).toHaveLength(1);
48
+ const facts = extractFacts(tracer.rootBuffers[0]);
49
+
50
+ // Should have started and ok facts
51
+ expect(facts.has(spanStarted('my-operation'))).toBe(true);
52
+ expect(facts.has(spanOk('my-operation'))).toBe(true);
53
+ });
54
+
55
+ it('extracts log facts', async () => {
56
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
57
+
58
+ await tracer.trace('with-logs', async (ctx) => {
59
+ ctx.log.info('Starting process');
60
+ ctx.log.warn('Something to note');
61
+ return ctx.ok('done');
62
+ });
63
+
64
+ const facts = extractFacts(tracer.rootBuffers[0]);
65
+
66
+ expect(facts.has(logInfo('Starting process'))).toBe(true);
67
+ expect(facts.has(logWarn('Something to note'))).toBe(true);
68
+ });
69
+
70
+ it('extracts tag facts from row 0', async () => {
71
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
72
+
73
+ await tracer.trace('with-tags', async (ctx) => {
74
+ ctx.tag.userId('user-123').orderId('order-456');
75
+ return ctx.ok('done');
76
+ });
77
+
78
+ const facts = extractFacts(tracer.rootBuffers[0]);
79
+
80
+ expect(facts.has(tagFact('userId', 'user-123'))).toBe(true);
81
+ expect(facts.has(tagFact('orderId', 'order-456'))).toBe(true);
82
+ });
83
+
84
+ it('extracts facts from nested spans in order', async () => {
85
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
86
+
87
+ await tracer.trace('parent', async (ctx) => {
88
+ await ctx.span('child-1', async (childCtx) => {
89
+ return childCtx.ok('child-1 done');
90
+ });
91
+
92
+ await ctx.span('child-2', async (childCtx) => {
93
+ return childCtx.ok('child-2 done');
94
+ });
95
+
96
+ return ctx.ok('parent done');
97
+ });
98
+
99
+ const facts = extractFacts(tracer.rootBuffers[0]);
100
+
101
+ // Check order: parent starts, child-1 complete, child-2 complete, parent completes
102
+ expect(
103
+ facts.hasInOrder([
104
+ spanStarted('parent'),
105
+ spanStarted('child-1'),
106
+ spanOk('child-1'),
107
+ spanStarted('child-2'),
108
+ spanOk('child-2'),
109
+ spanOk('parent'),
110
+ ]),
111
+ ).toBe(true);
112
+ });
113
+
114
+ it('extracts error facts from span:err', async () => {
115
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
116
+
117
+ await tracer.trace('failing-op', async (ctx) => {
118
+ return ctx.err(NOT_FOUND({ detail: 'Resource missing' }));
119
+ });
120
+
121
+ const facts = extractFacts(tracer.rootBuffers[0]);
122
+
123
+ expect(facts.has(spanStarted('failing-op'))).toBe(true);
124
+ expect(facts.has(spanErr('failing-op', 'NOT_FOUND'))).toBe(true);
125
+ expect(facts.has(spanOk('failing-op'))).toBe(false);
126
+ });
127
+
128
+ it('extracts feature flag access facts from system columns', async () => {
129
+ const tracer = new TestTracer(opContextWithFlags, {
130
+ ...createTestTracerOptions(),
131
+ flagEvaluator,
132
+ });
133
+
134
+ await tracer.trace('with-ff', async (ctx) => {
135
+ const validationFlag = ctx.ff.advancedValidation;
136
+ expect(validationFlag?.value).toBe(true);
137
+ return ctx.ok('done');
138
+ });
139
+
140
+ const facts = extractFacts(tracer.rootBuffers[0]);
141
+
142
+ expect(facts.has(ffFact('advancedValidation', 'true'))).toBe(true);
143
+ });
144
+
145
+ it('filters facts by namespace', async () => {
146
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
147
+
148
+ await tracer.trace('mixed', async (ctx) => {
149
+ ctx.log.info('A log message');
150
+ ctx.tag.userId('user-1');
151
+ return ctx.ok('done');
152
+ });
153
+
154
+ const facts = extractFacts(tracer.rootBuffers[0]);
155
+
156
+ // Filter to just span facts
157
+ const spanFacts = facts.byNamespace('span');
158
+ expect(spanFacts.length).toBe(2); // started + ok
159
+
160
+ // Filter to just log facts
161
+ const logFacts = facts.byNamespace('log');
162
+ expect(logFacts.length).toBe(1);
163
+
164
+ // Filter to just tag facts
165
+ const tagFacts = facts.byNamespace('tag');
166
+ expect(tagFacts.length).toBe(1);
167
+ });
168
+
169
+ it('supports pattern matching', async () => {
170
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
171
+
172
+ await tracer.trace('fetch-user', async (ctx) => {
173
+ await ctx.span('fetch-profile', async (c) => c.ok(null));
174
+ await ctx.span('fetch-orders', async (c) => c.ok(null));
175
+ return ctx.ok('done');
176
+ });
177
+
178
+ const facts = extractFacts(tracer.rootBuffers[0]);
179
+
180
+ // Match any fetch-* span that started
181
+ expect(facts.hasMatch('span:fetch-*: started')).toBe(true);
182
+
183
+ // Match any span that completed ok
184
+ expect(facts.hasMatch('span:*: ok')).toBe(true);
185
+
186
+ // Should match multiple
187
+ const fetchStarts = facts.match('span:fetch-*: started');
188
+ expect(fetchStarts.length).toBe(3); // fetch-user, fetch-profile, fetch-orders
189
+ });
190
+
191
+ it('handles deeply nested spans', async () => {
192
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
193
+
194
+ await tracer.trace('level-0', async (ctx) => {
195
+ await ctx.span('level-1', async (c1) => {
196
+ await c1.span('level-2', async (c2) => {
197
+ await c2.span('level-3', async (c3) => {
198
+ return c3.ok('deepest');
199
+ });
200
+ return c2.ok('l2');
201
+ });
202
+ return c1.ok('l1');
203
+ });
204
+ return ctx.ok('l0');
205
+ });
206
+
207
+ const facts = extractFacts(tracer.rootBuffers[0]);
208
+
209
+ // All levels should appear
210
+ expect(facts.has(spanStarted('level-0'))).toBe(true);
211
+ expect(facts.has(spanStarted('level-1'))).toBe(true);
212
+ expect(facts.has(spanStarted('level-2'))).toBe(true);
213
+ expect(facts.has(spanStarted('level-3'))).toBe(true);
214
+
215
+ // Inner spans complete before outer
216
+ expect(facts.hasInOrder([spanOk('level-3'), spanOk('level-2'), spanOk('level-1'), spanOk('level-0')])).toBe(true);
217
+ });
218
+ });
219
+
220
+ describe('trace-testing patterns', () => {
221
+ const testSchema = defineLogSchema({
222
+ sku: S.category(),
223
+ quantity: S.number(),
224
+ reservationId: S.category(),
225
+ });
226
+
227
+ const opContext = defineOpContext({ logSchema: testSchema });
228
+
229
+ it('example: verify operation order without implementation details', async () => {
230
+ const tracer = new TestTracer(opContext, { ...createTestTracerOptions() });
231
+
232
+ // Simulate an order processing workflow
233
+ await tracer.trace('process-order', async (ctx) => {
234
+ ctx.tag.sku('SKU-A').quantity(5);
235
+
236
+ // Validate
237
+ await ctx.span('validate', async (c) => {
238
+ c.log.info('Validating order');
239
+ return c.ok({ valid: true });
240
+ });
241
+
242
+ // Reserve inventory
243
+ await ctx.span('reserve-inventory', async (c) => {
244
+ c.tag.reservationId('res-123');
245
+ return c.ok({ reserved: true });
246
+ });
247
+
248
+ // Charge payment
249
+ await ctx.span('charge-payment', async (c) => {
250
+ c.log.info('Charging $49.99');
251
+ return c.ok({ charged: true });
252
+ });
253
+
254
+ return ctx.ok('Order processed');
255
+ });
256
+
257
+ const facts = extractFacts(tracer.rootBuffers[0]);
258
+
259
+ // Test WHAT happened, not HOW
260
+
261
+ // 1. Order was processed successfully
262
+ expect(facts.has(spanOk('process-order'))).toBe(true);
263
+
264
+ // 2. Validation happened before inventory reservation
265
+ expect(facts.hasInOrder([spanOk('validate'), spanStarted('reserve-inventory')])).toBe(true);
266
+
267
+ // 3. Inventory was reserved before payment was charged
268
+ expect(facts.hasInOrder([spanOk('reserve-inventory'), spanStarted('charge-payment')])).toBe(true);
269
+
270
+ // 4. Expected tags were set
271
+ expect(facts.has(tagFact('sku', 'SKU-A'))).toBe(true);
272
+ expect(facts.has(tagFact('quantity', 5))).toBe(true);
273
+ expect(facts.has(tagFact('reservationId', 'res-123'))).toBe(true);
274
+
275
+ // 5. No errors occurred
276
+ expect(facts.hasMatch('span:*: err(*)')).toBe(false);
277
+ expect(facts.hasMatch('log:error: *')).toBe(false);
278
+ });
279
+ });