@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.
- package/README.md +269 -0
- package/dist/allocator.wasm +0 -0
- package/dist/bun/preload.d.ts +11 -0
- package/dist/bun/preload.d.ts.map +1 -0
- package/dist/bun/preload.js +10 -0
- package/dist/bun/trace-preload.d.ts +8 -0
- package/dist/bun/trace-preload.d.ts.map +1 -0
- package/dist/bun/trace-preload.js +12 -0
- package/dist/es.d.ts +8 -0
- package/dist/es.d.ts.map +1 -0
- package/dist/es.js +9 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/lib/JsBufferStrategy.d.ts +49 -0
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
- package/dist/lib/JsBufferStrategy.js +60 -0
- package/dist/lib/archive/chunkCompaction.d.ts +15 -0
- package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
- package/dist/lib/archive/chunkCompaction.js +24 -0
- package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
- package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
- package/dist/lib/archive/chunkEnvelope.js +55 -0
- package/dist/lib/archive/chunkRouting.d.ts +10 -0
- package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
- package/dist/lib/archive/chunkRouting.js +47 -0
- package/dist/lib/archive/chunkStats.d.ts +12 -0
- package/dist/lib/archive/chunkStats.d.ts.map +1 -0
- package/dist/lib/archive/chunkStats.js +10 -0
- package/dist/lib/archive/index.d.ts +5 -0
- package/dist/lib/archive/index.d.ts.map +1 -0
- package/dist/lib/archive/index.js +4 -0
- package/dist/lib/arrow/capacityStats.d.ts +9 -0
- package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
- package/dist/lib/arrow/capacityStats.js +231 -0
- package/dist/lib/arrow/dictionaries.d.ts +27 -0
- package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
- package/dist/lib/arrow/dictionaries.js +135 -0
- package/dist/lib/arrow/flechette.d.ts +40 -0
- package/dist/lib/arrow/flechette.d.ts.map +1 -0
- package/dist/lib/arrow/flechette.js +67 -0
- package/dist/lib/arrow/utils.d.ts +38 -0
- package/dist/lib/arrow/utils.d.ts.map +1 -0
- package/dist/lib/arrow/utils.js +112 -0
- package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
- package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
- package/dist/lib/buffer/Nanoseconds.js +86 -0
- package/dist/lib/bufferStrategy.d.ts +95 -0
- package/dist/lib/bufferStrategy.d.ts.map +1 -0
- package/dist/lib/bufferStrategy.js +1 -0
- package/dist/lib/capacityTuning.d.ts +50 -0
- package/dist/lib/capacityTuning.d.ts.map +1 -0
- package/dist/lib/capacityTuning.js +65 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/evaluatorGenerator.js +199 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
- package/dist/lib/convertToArrow.d.ts +40 -0
- package/dist/lib/convertToArrow.d.ts.map +1 -0
- package/dist/lib/convertToArrow.js +1467 -0
- package/dist/lib/defineOpContext.d.ts +96 -0
- package/dist/lib/defineOpContext.d.ts.map +1 -0
- package/dist/lib/defineOpContext.js +227 -0
- package/dist/lib/errors/Blocked.d.ts +113 -0
- package/dist/lib/errors/Blocked.d.ts.map +1 -0
- package/dist/lib/errors/Blocked.js +68 -0
- package/dist/lib/errors/CodeError.d.ts +101 -0
- package/dist/lib/errors/CodeError.d.ts.map +1 -0
- package/dist/lib/errors/CodeError.js +42 -0
- package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
- package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
- package/dist/lib/errors/RetriesExhausted.js +31 -0
- package/dist/lib/errors/Transient.d.ts +115 -0
- package/dist/lib/errors/Transient.d.ts.map +1 -0
- package/dist/lib/errors/Transient.js +54 -0
- package/dist/lib/errors/index.d.ts +14 -0
- package/dist/lib/errors/index.d.ts.map +1 -0
- package/dist/lib/errors/index.js +16 -0
- package/dist/lib/errors/retry-policy.d.ts +60 -0
- package/dist/lib/errors/retry-policy.d.ts.map +1 -0
- package/dist/lib/errors/retry-policy.js +54 -0
- package/dist/lib/flushScheduler.d.ts +162 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -0
- package/dist/lib/flushScheduler.js +388 -0
- package/dist/lib/library.d.ts +149 -0
- package/dist/lib/library.d.ts.map +1 -0
- package/dist/lib/library.js +588 -0
- package/dist/lib/logApi.d.ts +61 -0
- package/dist/lib/logApi.d.ts.map +1 -0
- package/dist/lib/logApi.js +12 -0
- package/dist/lib/logBinding.d.ts +63 -0
- package/dist/lib/logBinding.d.ts.map +1 -0
- package/dist/lib/logBinding.js +1 -0
- package/dist/lib/op.d.ts +105 -0
- package/dist/lib/op.d.ts.map +1 -0
- package/dist/lib/op.js +59 -0
- package/dist/lib/opContext/contextTypes.d.ts +88 -0
- package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/contextTypes.js +34 -0
- package/dist/lib/opContext/createOpGroup.d.ts +57 -0
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
- package/dist/lib/opContext/createOpGroup.js +341 -0
- package/dist/lib/opContext/defineOp.d.ts +83 -0
- package/dist/lib/opContext/defineOp.d.ts.map +1 -0
- package/dist/lib/opContext/defineOp.js +197 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
- package/dist/lib/opContext/featureFlagTypes.js +1 -0
- package/dist/lib/opContext/index.d.ts +13 -0
- package/dist/lib/opContext/index.d.ts.map +1 -0
- package/dist/lib/opContext/index.js +15 -0
- package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
- package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opGroupTypes.js +31 -0
- package/dist/lib/opContext/opTypes.d.ts +48 -0
- package/dist/lib/opContext/opTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opTypes.js +7 -0
- package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/spanContextTypes.js +1 -0
- package/dist/lib/opContext/types.d.ts +297 -0
- package/dist/lib/opContext/types.d.ts.map +1 -0
- package/dist/lib/opContext/types.js +16 -0
- package/dist/lib/result.d.ts +308 -0
- package/dist/lib/result.d.ts.map +1 -0
- package/dist/lib/result.js +359 -0
- package/dist/lib/schema/LogSchema.d.ts +62 -0
- package/dist/lib/schema/LogSchema.d.ts.map +1 -0
- package/dist/lib/schema/LogSchema.js +134 -0
- package/dist/lib/schema/builder.d.ts +12 -0
- package/dist/lib/schema/builder.d.ts.map +1 -0
- package/dist/lib/schema/builder.js +169 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
- package/dist/lib/schema/defineFeatureFlags.js +29 -0
- package/dist/lib/schema/defineLogSchema.d.ts +87 -0
- package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
- package/dist/lib/schema/defineLogSchema.js +171 -0
- package/dist/lib/schema/evaluator.d.ts +267 -0
- package/dist/lib/schema/evaluator.d.ts.map +1 -0
- package/dist/lib/schema/evaluator.js +169 -0
- package/dist/lib/schema/extend.d.ts +14 -0
- package/dist/lib/schema/extend.d.ts.map +1 -0
- package/dist/lib/schema/extend.js +51 -0
- package/dist/lib/schema/systemSchema.d.ts +112 -0
- package/dist/lib/schema/systemSchema.d.ts.map +1 -0
- package/dist/lib/schema/systemSchema.js +260 -0
- package/dist/lib/schema/typeGuards.d.ts +52 -0
- package/dist/lib/schema/typeGuards.d.ts.map +1 -0
- package/dist/lib/schema/typeGuards.js +127 -0
- package/dist/lib/schema/types.d.ts +156 -0
- package/dist/lib/schema/types.d.ts.map +1 -0
- package/dist/lib/schema/types.js +4 -0
- package/dist/lib/spanBuffer.d.ts +133 -0
- package/dist/lib/spanBuffer.d.ts.map +1 -0
- package/dist/lib/spanBuffer.js +442 -0
- package/dist/lib/spanBufferHelpers.d.ts +53 -0
- package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
- package/dist/lib/spanBufferHelpers.js +65 -0
- package/dist/lib/spanBufferStats.d.ts +38 -0
- package/dist/lib/spanBufferStats.d.ts.map +1 -0
- package/dist/lib/spanBufferStats.js +1 -0
- package/dist/lib/spanContext.d.ts +141 -0
- package/dist/lib/spanContext.d.ts.map +1 -0
- package/dist/lib/spanContext.js +763 -0
- package/dist/lib/sqlite/index.d.ts +14 -0
- package/dist/lib/sqlite/index.d.ts.map +1 -0
- package/dist/lib/sqlite/index.js +12 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
- package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-common.js +207 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-d1.js +67 -0
- package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
- package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-db.js +1 -0
- package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
- package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-node.js +68 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-writer.js +78 -0
- package/dist/lib/testing/bun-harness.d.ts +150 -0
- package/dist/lib/testing/bun-harness.d.ts.map +1 -0
- package/dist/lib/testing/bun-harness.js +729 -0
- package/dist/lib/testing/extractFacts.d.ts +73 -0
- package/dist/lib/testing/extractFacts.d.ts.map +1 -0
- package/dist/lib/testing/extractFacts.js +237 -0
- package/dist/lib/testing/facts.d.ts +235 -0
- package/dist/lib/testing/facts.d.ts.map +1 -0
- package/dist/lib/testing/facts.js +209 -0
- package/dist/lib/testing/index.d.ts +58 -0
- package/dist/lib/testing/index.d.ts.map +1 -0
- package/dist/lib/testing/index.js +74 -0
- package/dist/lib/testing/queryable-span.d.ts +39 -0
- package/dist/lib/testing/queryable-span.d.ts.map +1 -0
- package/dist/lib/testing/queryable-span.js +58 -0
- package/dist/lib/testing/span-query.d.ts +21 -0
- package/dist/lib/testing/span-query.d.ts.map +1 -0
- package/dist/lib/testing/span-query.js +47 -0
- package/dist/lib/testing/stdio-replay.d.ts +4 -0
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
- package/dist/lib/testing/stdio-replay.js +42 -0
- package/dist/lib/testing/trace-query.d.ts +59 -0
- package/dist/lib/testing/trace-query.d.ts.map +1 -0
- package/dist/lib/testing/trace-query.js +462 -0
- package/dist/lib/testing/vitest-harness.d.ts +135 -0
- package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
- package/dist/lib/testing/vitest-harness.js +486 -0
- package/dist/lib/threadId.d.ts +58 -0
- package/dist/lib/threadId.d.ts.map +1 -0
- package/dist/lib/threadId.js +123 -0
- package/dist/lib/traceContext.d.ts +116 -0
- package/dist/lib/traceContext.d.ts.map +1 -0
- package/dist/lib/traceContext.js +37 -0
- package/dist/lib/traceId.d.ts +78 -0
- package/dist/lib/traceId.d.ts.map +1 -0
- package/dist/lib/traceId.js +87 -0
- package/dist/lib/traceRoot.d.ts +133 -0
- package/dist/lib/traceRoot.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.d.ts +75 -0
- package/dist/lib/traceRoot.es.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.js +129 -0
- package/dist/lib/traceRoot.js +19 -0
- package/dist/lib/traceRoot.node.d.ts +77 -0
- package/dist/lib/traceRoot.node.d.ts.map +1 -0
- package/dist/lib/traceRoot.node.js +133 -0
- package/dist/lib/traceRoot.universal.d.ts +3 -0
- package/dist/lib/traceRoot.universal.d.ts.map +1 -0
- package/dist/lib/traceRoot.universal.js +17 -0
- package/dist/lib/tracer.d.ts +296 -0
- package/dist/lib/tracer.d.ts.map +1 -0
- package/dist/lib/tracer.js +346 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
- package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
- package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
- package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
- package/dist/lib/tracers/CompositeTracer.js +57 -0
- package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
- package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
- package/dist/lib/tracers/NoOpTracer.js +41 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
- package/dist/lib/tracers/SQLiteTracer.js +84 -0
- package/dist/lib/tracers/StdioTracer.d.ts +83 -0
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
- package/dist/lib/tracers/StdioTracer.js +270 -0
- package/dist/lib/tracers/TestTracer.d.ts +95 -0
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
- package/dist/lib/tracers/TestTracer.js +87 -0
- package/dist/lib/tracers/index.d.ts +12 -0
- package/dist/lib/tracers/index.d.ts.map +1 -0
- package/dist/lib/tracers/index.js +11 -0
- package/dist/lib/types.d.ts +366 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utf8Cache.d.ts +111 -0
- package/dist/lib/utf8Cache.d.ts.map +1 -0
- package/dist/lib/utf8Cache.js +177 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
- package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
- package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
- package/dist/lib/wasm/wasmAllocator.js +227 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
- package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
- package/dist/lib/wasm/wasmTraceRoot.js +264 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +8 -0
- package/dist/testing.d.ts +18 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +17 -0
- package/package.json +193 -0
- package/src/bun/preload.ts +11 -0
- package/src/bun/trace-preload.ts +14 -0
- package/src/es.ts +11 -0
- package/src/index.ts +194 -0
- package/src/lib/JsBufferStrategy.ts +102 -0
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
- package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
- package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
- package/src/lib/__tests__/binary-e2e.test.ts +203 -0
- package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
- package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
- package/src/lib/__tests__/effective-schema.test.ts +439 -0
- package/src/lib/__tests__/flechette.test.ts +42 -0
- package/src/lib/__tests__/flushScheduler.test.ts +537 -0
- package/src/lib/__tests__/integration.test.ts +600 -0
- package/src/lib/__tests__/library.test.ts +934 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
- package/src/lib/__tests__/op-context-binding.test.ts +135 -0
- package/src/lib/__tests__/op-metadata.test.ts +198 -0
- package/src/lib/__tests__/op-type-safety.test.ts +71 -0
- package/src/lib/__tests__/package-exports.test.ts +57 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
- package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
- package/src/lib/__tests__/scope-attributes.test.ts +348 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
- package/src/lib/__tests__/test-helpers.ts +318 -0
- package/src/lib/__tests__/timestamp.test.ts +259 -0
- package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
- package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
- package/src/lib/__tests__/tracer.test.ts +211 -0
- package/src/lib/__tests__/type-narrowing.test.ts +137 -0
- package/src/lib/archive/chunkCompaction.ts +44 -0
- package/src/lib/archive/chunkEnvelope.ts +79 -0
- package/src/lib/archive/chunkRouting.ts +70 -0
- package/src/lib/archive/chunkStats.ts +25 -0
- package/src/lib/archive/index.ts +4 -0
- package/src/lib/arrow/capacityStats.ts +340 -0
- package/src/lib/arrow/dictionaries.ts +159 -0
- package/src/lib/arrow/flechette.ts +114 -0
- package/src/lib/arrow/utils.ts +126 -0
- package/src/lib/buffer/Nanoseconds.ts +131 -0
- package/src/lib/bufferStrategy.ts +106 -0
- package/src/lib/capacityTuning.ts +102 -0
- package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
- package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
- package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
- package/src/lib/codegen/evaluatorGenerator.ts +309 -0
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
- package/src/lib/convertToArrow.ts +1805 -0
- package/src/lib/defineOpContext.ts +398 -0
- package/src/lib/errors/Blocked.ts +165 -0
- package/src/lib/errors/CodeError.ts +132 -0
- package/src/lib/errors/RetriesExhausted.ts +78 -0
- package/src/lib/errors/Transient.ts +168 -0
- package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
- package/src/lib/errors/__tests__/Transient.test.ts +129 -0
- package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
- package/src/lib/errors/index.ts +24 -0
- package/src/lib/errors/retry-policy.ts +87 -0
- package/src/lib/flushScheduler.ts +509 -0
- package/src/lib/library.ts +682 -0
- package/src/lib/logApi.ts +70 -0
- package/src/lib/logBinding.ts +67 -0
- package/src/lib/op.ts +103 -0
- package/src/lib/opContext/__tests__/retry.test.ts +764 -0
- package/src/lib/opContext/contextTypes.ts +130 -0
- package/src/lib/opContext/createOpGroup.ts +456 -0
- package/src/lib/opContext/defineOp.ts +281 -0
- package/src/lib/opContext/featureFlagTypes.ts +54 -0
- package/src/lib/opContext/index.ts +16 -0
- package/src/lib/opContext/opGroupTypes.ts +342 -0
- package/src/lib/opContext/opTypes.ts +80 -0
- package/src/lib/opContext/spanContextTypes.ts +398 -0
- package/src/lib/opContext/types.ts +403 -0
- package/src/lib/result.ts +550 -0
- package/src/lib/schema/LogSchema.ts +153 -0
- package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
- package/src/lib/schema/builder.ts +201 -0
- package/src/lib/schema/defineFeatureFlags.ts +91 -0
- package/src/lib/schema/defineLogSchema.ts +291 -0
- package/src/lib/schema/evaluator.ts +404 -0
- package/src/lib/schema/extend.ts +69 -0
- package/src/lib/schema/systemSchema.ts +339 -0
- package/src/lib/schema/typeGuards.ts +163 -0
- package/src/lib/schema/types.ts +265 -0
- package/src/lib/spanBuffer.ts +571 -0
- package/src/lib/spanBufferHelpers.ts +73 -0
- package/src/lib/spanBufferStats.ts +40 -0
- package/src/lib/spanContext.ts +1566 -0
- package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
- package/src/lib/sqlite/index.ts +26 -0
- package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
- package/src/lib/sqlite/sqlite-common.ts +309 -0
- package/src/lib/sqlite/sqlite-d1.ts +104 -0
- package/src/lib/sqlite/sqlite-db.ts +32 -0
- package/src/lib/sqlite/sqlite-node.ts +83 -0
- package/src/lib/sqlite/sqlite-writer.ts +128 -0
- package/src/lib/testing/TRACE-TESTING.md +100 -0
- package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
- package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
- package/src/lib/testing/__tests__/facts.test.ts +324 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
- package/src/lib/testing/bun-harness.ts +990 -0
- package/src/lib/testing/extractFacts.ts +362 -0
- package/src/lib/testing/facts.ts +470 -0
- package/src/lib/testing/index.ts +141 -0
- package/src/lib/testing/queryable-span.ts +108 -0
- package/src/lib/testing/span-query.ts +65 -0
- package/src/lib/testing/stdio-replay.ts +50 -0
- package/src/lib/testing/trace-query.ts +329 -0
- package/src/lib/testing/vitest-harness.ts +691 -0
- package/src/lib/threadId.ts +135 -0
- package/src/lib/traceContext.ts +182 -0
- package/src/lib/traceId.ts +142 -0
- package/src/lib/traceRoot.es.ts +157 -0
- package/src/lib/traceRoot.node.ts +170 -0
- package/src/lib/traceRoot.ts +154 -0
- package/src/lib/traceRoot.universal.ts +22 -0
- package/src/lib/tracer.ts +896 -0
- package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
- package/src/lib/tracers/CompositeTracer.ts +76 -0
- package/src/lib/tracers/NoOpTracer.ts +73 -0
- package/src/lib/tracers/SQLiteTracer.ts +115 -0
- package/src/lib/tracers/StdioTracer.ts +380 -0
- package/src/lib/tracers/TestTracer.ts +146 -0
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
- package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
- package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
- package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
- package/src/lib/tracers/index.ts +12 -0
- package/src/lib/types.ts +498 -0
- package/src/lib/utf8Cache.ts +201 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
- package/src/lib/wasm/allocator.zig +945 -0
- package/src/lib/wasm/wasmAllocator.ts +469 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
- package/src/lib/wasm/wasmTraceRoot.ts +315 -0
- package/src/node.ts +10 -0
- package/src/testing.ts +18 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { createBuffer, createTestLogBinding, createTestSchema } from '../../__tests__/test-helpers.js';
|
|
3
|
+
import type { OpContext } from '../../opContext/types.js';
|
|
4
|
+
import { S } from '../../schema/builder.js';
|
|
5
|
+
import type { FeatureFlagSchema } from '../../schema/defineFeatureFlags.js';
|
|
6
|
+
import { defineFeatureFlags } from '../../schema/defineFeatureFlags.js';
|
|
7
|
+
import { InMemoryFlagEvaluator } from '../../schema/evaluator.js';
|
|
8
|
+
import { ENTRY_TYPE_FF_ACCESS, ENTRY_TYPE_FF_USAGE } from '../../schema/systemSchema.js';
|
|
9
|
+
import type { LogSchema } from '../../schema/types.js';
|
|
10
|
+
import { createSpanContextClass, type SpanContextInstance } from '../../spanContext.js';
|
|
11
|
+
import type { AnySpanBuffer, SpanBuffer } from '../../types.js';
|
|
12
|
+
import { createEvaluatorClass, generateEvaluatorClass } from '../evaluatorGenerator.js';
|
|
13
|
+
import { createTagWriter } from '../fixedPositionWriterGenerator.js';
|
|
14
|
+
import { createSpanLogger } from '../spanLoggerGenerator.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a mock SpanContext for testing FeatureFlagEvaluator
|
|
18
|
+
*
|
|
19
|
+
* The evaluator needs:
|
|
20
|
+
* - _buffer with scopeValues and writeIndex
|
|
21
|
+
* - log with ffAccess, ffUsage, and _writeIndex
|
|
22
|
+
* - buffer getter that returns _buffer
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
type EvaluatorTestContext<TLogSchema extends LogSchema, TFlags extends FeatureFlagSchema> = OpContext<
|
|
26
|
+
TLogSchema,
|
|
27
|
+
TFlags,
|
|
28
|
+
Record<string, never>,
|
|
29
|
+
Record<string, never>
|
|
30
|
+
>;
|
|
31
|
+
|
|
32
|
+
function createMockSpanContext<TLogSchema extends LogSchema, TFlags extends FeatureFlagSchema>(
|
|
33
|
+
schema: TLogSchema,
|
|
34
|
+
spanBuffer: SpanBuffer<TLogSchema>,
|
|
35
|
+
): SpanContextInstance<EvaluatorTestContext<TLogSchema, TFlags>> {
|
|
36
|
+
const logger = createSpanLogger(schema, spanBuffer);
|
|
37
|
+
const tagWriter = createTagWriter(schema, spanBuffer);
|
|
38
|
+
const SpanContextClass = createSpanContextClass<EvaluatorTestContext<TLogSchema, TFlags>>(
|
|
39
|
+
schema,
|
|
40
|
+
createTestLogBinding(schema),
|
|
41
|
+
);
|
|
42
|
+
const ctx = new SpanContextClass(spanBuffer, schema, logger, tagWriter);
|
|
43
|
+
ctx.deps = {};
|
|
44
|
+
return ctx;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('EvaluatorGenerator', () => {
|
|
48
|
+
describe('generateEvaluatorClass', () => {
|
|
49
|
+
test('generates valid JavaScript class code', () => {
|
|
50
|
+
const schema = defineFeatureFlags({
|
|
51
|
+
debugMode: S.boolean().default(false).sync(),
|
|
52
|
+
maxRetries: S.number().default(3).sync(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
56
|
+
|
|
57
|
+
expect(code).toContain('class GeneratedEvaluator extends WorkerSafeGeneratedEvaluator');
|
|
58
|
+
expect(code).toContain('Object.defineProperties(GeneratedEvaluator.prototype');
|
|
59
|
+
|
|
60
|
+
// Should describe the generated getters for each flag
|
|
61
|
+
expect(code).toContain("return this.getFlag('debugMode')");
|
|
62
|
+
expect(code).toContain("return this.getFlag('maxRetries')");
|
|
63
|
+
|
|
64
|
+
// Should have new API methods (not old ones)
|
|
65
|
+
expect(code).toContain('forContext(ctx)');
|
|
66
|
+
expect(code).toContain('super(spanContext, evaluator, SCHEMA, validateFlagValue, ENTRY_TYPE_FF_ACCESS);');
|
|
67
|
+
|
|
68
|
+
// Should NOT have old API methods
|
|
69
|
+
expect(code).not.toContain('withBuffer(');
|
|
70
|
+
expect(code).not.toContain('getContext()');
|
|
71
|
+
expect(code).not.toContain('new Function');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('generates unique getter for each flag', () => {
|
|
75
|
+
const schema = defineFeatureFlags({
|
|
76
|
+
featureA: S.boolean().default(false).sync(),
|
|
77
|
+
featureB: S.boolean().default(false).sync(),
|
|
78
|
+
featureC: S.number().default(0).sync(),
|
|
79
|
+
featureD: S.enum(['a', 'b', 'c'] as const)
|
|
80
|
+
.default('a')
|
|
81
|
+
.sync(),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
85
|
+
|
|
86
|
+
expect(code).toContain('featureA: {');
|
|
87
|
+
expect(code).toContain('featureB: {');
|
|
88
|
+
expect(code).toContain('featureC: {');
|
|
89
|
+
expect(code).toContain('featureD: {');
|
|
90
|
+
|
|
91
|
+
// Each getter should call getFlag with the flag name
|
|
92
|
+
expect(code).toContain("this.getFlag('featureA')");
|
|
93
|
+
expect(code).toContain("this.getFlag('featureB')");
|
|
94
|
+
expect(code).toContain("this.getFlag('featureC')");
|
|
95
|
+
expect(code).toContain("this.getFlag('featureD')");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('createEvaluatorClass', () => {
|
|
100
|
+
test('creates a functional class constructor', () => {
|
|
101
|
+
const ffSchema = defineFeatureFlags({
|
|
102
|
+
debugMode: S.boolean().default(false).sync(),
|
|
103
|
+
});
|
|
104
|
+
const logSchema = createTestSchema({});
|
|
105
|
+
const spanBuffer = createBuffer(logSchema);
|
|
106
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
107
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
108
|
+
|
|
109
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
110
|
+
ffSchema.schema,
|
|
111
|
+
(value, _schema, def) => value ?? def,
|
|
112
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
expect(typeof GeneratedClass).toBe('function');
|
|
116
|
+
|
|
117
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
118
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
119
|
+
expect(instance).toBeDefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('caches generated classes by schema', () => {
|
|
123
|
+
const schema = defineFeatureFlags({
|
|
124
|
+
testFlag: S.boolean().default(false).sync(),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const Class1 = createEvaluatorClass(schema.schema, (value, _schema, def) => value ?? def, ENTRY_TYPE_FF_ACCESS);
|
|
128
|
+
|
|
129
|
+
const Class2 = createEvaluatorClass(schema.schema, (value, _schema, def) => value ?? def, ENTRY_TYPE_FF_ACCESS);
|
|
130
|
+
|
|
131
|
+
// Same schema should return same class (cached)
|
|
132
|
+
expect(Class1).toBe(Class2);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('generates different classes for different schemas', () => {
|
|
136
|
+
const schema1 = defineFeatureFlags({
|
|
137
|
+
flagA: S.boolean().default(false).sync(),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const schema2 = defineFeatureFlags({
|
|
141
|
+
flagB: S.boolean().default(false).sync(),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const Class1 = createEvaluatorClass(schema1.schema, (value, _schema, def) => value ?? def, ENTRY_TYPE_FF_ACCESS);
|
|
145
|
+
|
|
146
|
+
const Class2 = createEvaluatorClass(schema2.schema, (value, _schema, def) => value ?? def, ENTRY_TYPE_FF_ACCESS);
|
|
147
|
+
|
|
148
|
+
// Different schemas should generate different classes
|
|
149
|
+
expect(Class1).not.toBe(Class2);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('Generated class functionality', () => {
|
|
154
|
+
test('flag getters return FlagContext for truthy values', () => {
|
|
155
|
+
const ffSchema = defineFeatureFlags({
|
|
156
|
+
debugMode: S.boolean().default(false).sync(),
|
|
157
|
+
});
|
|
158
|
+
const logSchema = createTestSchema({});
|
|
159
|
+
const spanBuffer = createBuffer(logSchema);
|
|
160
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
161
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
162
|
+
|
|
163
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
164
|
+
ffSchema.schema,
|
|
165
|
+
(value, _schema, def) => value ?? def,
|
|
166
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
170
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
171
|
+
|
|
172
|
+
// Access the flag via generated getter
|
|
173
|
+
const flag = Reflect.get(instance, 'debugMode');
|
|
174
|
+
|
|
175
|
+
expect(flag).toBeDefined();
|
|
176
|
+
expect(flag?.value).toBe(true);
|
|
177
|
+
expect(typeof flag?.track).toBe('function');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('flag getters return undefined for falsy values', () => {
|
|
181
|
+
const ffSchema = defineFeatureFlags({
|
|
182
|
+
debugMode: S.boolean().default(false).sync(),
|
|
183
|
+
});
|
|
184
|
+
const logSchema = createTestSchema({});
|
|
185
|
+
const spanBuffer = createBuffer(logSchema);
|
|
186
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
187
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
188
|
+
|
|
189
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
190
|
+
ffSchema.schema,
|
|
191
|
+
(value, _schema, def) => value ?? def,
|
|
192
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: false });
|
|
196
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
197
|
+
|
|
198
|
+
const flag = Reflect.get(instance, 'debugMode');
|
|
199
|
+
expect(flag).toBeUndefined();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('forContext creates new instance bound to new SpanContext', () => {
|
|
203
|
+
const ffSchema = defineFeatureFlags({
|
|
204
|
+
debugMode: S.boolean().default(false).sync(),
|
|
205
|
+
});
|
|
206
|
+
const logSchema = createTestSchema({});
|
|
207
|
+
const spanBuffer = createBuffer(logSchema);
|
|
208
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
209
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
210
|
+
|
|
211
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
212
|
+
ffSchema.schema,
|
|
213
|
+
(value, _schema, def) => value ?? def,
|
|
214
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
218
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
219
|
+
|
|
220
|
+
// Create a new SpanContext for child span
|
|
221
|
+
const childBuffer = createBuffer(logSchema);
|
|
222
|
+
const childCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, childBuffer);
|
|
223
|
+
|
|
224
|
+
const childInstance = instance.forContext(childCtx);
|
|
225
|
+
|
|
226
|
+
// Child should have flag accessible
|
|
227
|
+
const childFlag = Reflect.get(childInstance, 'debugMode');
|
|
228
|
+
expect(childFlag?.value).toBe(true);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('span context scope getter returns the typed buffer scope contract', () => {
|
|
232
|
+
const ffSchema = defineFeatureFlags({
|
|
233
|
+
debugMode: S.boolean().default(false).sync(),
|
|
234
|
+
});
|
|
235
|
+
const logSchema = createTestSchema({
|
|
236
|
+
requestId: S.category(),
|
|
237
|
+
});
|
|
238
|
+
const spanBuffer = createBuffer(logSchema);
|
|
239
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
240
|
+
|
|
241
|
+
spanBuffer._scopeValues = Object.freeze({ requestId: 'req-123' });
|
|
242
|
+
|
|
243
|
+
const scope = mockCtx.scope;
|
|
244
|
+
expect(scope).toBe(spanBuffer._scopeValues);
|
|
245
|
+
expect(scope.requestId).toBe('req-123');
|
|
246
|
+
|
|
247
|
+
expect(typeof scope.requestId).toBe('string');
|
|
248
|
+
if (typeof scope.requestId === 'string') {
|
|
249
|
+
const requestId = scope.requestId;
|
|
250
|
+
expect(requestId).toBe('req-123');
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test('flag access is deduplicated via buffer scan', () => {
|
|
255
|
+
const ffSchema = defineFeatureFlags({
|
|
256
|
+
debugMode: S.boolean().default(false).sync(),
|
|
257
|
+
});
|
|
258
|
+
const logSchema = createTestSchema({});
|
|
259
|
+
const spanBuffer = createBuffer(logSchema);
|
|
260
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
261
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
262
|
+
|
|
263
|
+
let evalCount = 0;
|
|
264
|
+
const trackingEvaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
265
|
+
const baseGetSync = trackingEvaluator.getSync.bind(trackingEvaluator);
|
|
266
|
+
trackingEvaluator.getSync = (ctx, flag) => {
|
|
267
|
+
evalCount++;
|
|
268
|
+
return baseGetSync(ctx, flag);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
272
|
+
ffSchema.schema,
|
|
273
|
+
(value, _schema, def) => value ?? def,
|
|
274
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const instance = new GeneratedClass(mockCtx, trackingEvaluator);
|
|
278
|
+
|
|
279
|
+
// Access flag multiple times
|
|
280
|
+
Reflect.get(instance, 'debugMode');
|
|
281
|
+
Reflect.get(instance, 'debugMode');
|
|
282
|
+
Reflect.get(instance, 'debugMode');
|
|
283
|
+
|
|
284
|
+
// Evaluator should be called each time (no local cache)
|
|
285
|
+
expect(evalCount).toBe(3);
|
|
286
|
+
|
|
287
|
+
// But ff-access should only be logged once (buffer deduplication)
|
|
288
|
+
const accessCount = countEntryType(spanBuffer, ENTRY_TYPE_FF_ACCESS);
|
|
289
|
+
expect(accessCount).toBe(1);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test('async get method works correctly', async () => {
|
|
293
|
+
const ffSchema = defineFeatureFlags({
|
|
294
|
+
asyncFlag: S.number().default(100).async(),
|
|
295
|
+
});
|
|
296
|
+
const logSchema = createTestSchema({});
|
|
297
|
+
const spanBuffer = createBuffer(logSchema);
|
|
298
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
299
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
300
|
+
|
|
301
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
302
|
+
ffSchema.schema,
|
|
303
|
+
(value, _schema, def) => value ?? def,
|
|
304
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { asyncFlag: 200 });
|
|
308
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
309
|
+
const result = await instance.get('asyncFlag');
|
|
310
|
+
|
|
311
|
+
expect(result).toBeDefined();
|
|
312
|
+
if (!result) {
|
|
313
|
+
throw new Error('Expected asyncFlag to produce a flag context');
|
|
314
|
+
}
|
|
315
|
+
expect(result.value).toBe(200);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('track() logs ff-usage entry via logger', () => {
|
|
319
|
+
const ffSchema = defineFeatureFlags({
|
|
320
|
+
debugMode: S.boolean().default(false).sync(),
|
|
321
|
+
});
|
|
322
|
+
const logSchema = createTestSchema({
|
|
323
|
+
action: S.category(),
|
|
324
|
+
outcome: S.category(),
|
|
325
|
+
});
|
|
326
|
+
const spanBuffer = createBuffer(logSchema);
|
|
327
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
328
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
329
|
+
|
|
330
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
331
|
+
ffSchema.schema,
|
|
332
|
+
(value, _schema, def) => value ?? def,
|
|
333
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
337
|
+
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
338
|
+
|
|
339
|
+
const flag = Reflect.get(instance, 'debugMode');
|
|
340
|
+
flag?.track({ action: 'test_action', outcome: 'success' });
|
|
341
|
+
|
|
342
|
+
// Check buffer for ff-usage entry
|
|
343
|
+
const usageCount = countEntryType(spanBuffer, ENTRY_TYPE_FF_USAGE);
|
|
344
|
+
expect(usageCount).toBe(1);
|
|
345
|
+
|
|
346
|
+
// Context should be applied via with(context)
|
|
347
|
+
let usageIdx = -1;
|
|
348
|
+
for (let i = 0; i < spanBuffer._writeIndex; i++) {
|
|
349
|
+
if (spanBuffer.entry_type[i] === ENTRY_TYPE_FF_USAGE) {
|
|
350
|
+
usageIdx = i;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
expect(usageIdx).toBeGreaterThanOrEqual(0);
|
|
355
|
+
expect(spanBuffer.action_values?.[usageIdx]).toBe('test_action');
|
|
356
|
+
expect(spanBuffer.outcome_values?.[usageIdx]).toBe('success');
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
describe('V8 optimization verification', () => {
|
|
361
|
+
test('generated class has stable shape (all instances have same properties)', () => {
|
|
362
|
+
const schema = defineFeatureFlags({
|
|
363
|
+
flag1: S.boolean().default(false).sync(),
|
|
364
|
+
flag2: S.number().default(0).sync(),
|
|
365
|
+
});
|
|
366
|
+
const logSchema = createTestSchema({});
|
|
367
|
+
type Ctx = EvaluatorTestContext<typeof logSchema, typeof schema.schema>;
|
|
368
|
+
|
|
369
|
+
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
370
|
+
schema.schema,
|
|
371
|
+
(value, _s, def) => value ?? def,
|
|
372
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
const mockEvaluator = new InMemoryFlagEvaluator<Ctx>(schema.schema, {});
|
|
376
|
+
|
|
377
|
+
const createInstance = () => {
|
|
378
|
+
const spanBuffer = createBuffer(logSchema);
|
|
379
|
+
const mockCtx = createMockSpanContext<typeof logSchema, typeof schema.schema>(logSchema, spanBuffer);
|
|
380
|
+
return new GeneratedClass(mockCtx, mockEvaluator);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const instance1 = createInstance();
|
|
384
|
+
const instance2 = createInstance();
|
|
385
|
+
|
|
386
|
+
// Both instances should have the same property names (stable hidden class)
|
|
387
|
+
const props1 = Object.getOwnPropertyNames(Object.getPrototypeOf(instance1));
|
|
388
|
+
const props2 = Object.getOwnPropertyNames(Object.getPrototypeOf(instance2));
|
|
389
|
+
|
|
390
|
+
expect(props1).toEqual(props2);
|
|
391
|
+
|
|
392
|
+
// Should have getters as own properties on prototype
|
|
393
|
+
expect(props1).toContain('flag1');
|
|
394
|
+
expect(props1).toContain('flag2');
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('generated getters are real property descriptors (not proxy traps)', () => {
|
|
398
|
+
const schema = defineFeatureFlags({
|
|
399
|
+
testFlag: S.boolean().default(false).sync(),
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const GeneratedClass = createEvaluatorClass(
|
|
403
|
+
schema.schema,
|
|
404
|
+
(value, _s, def) => value ?? def,
|
|
405
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
// Check the prototype for getter descriptors
|
|
409
|
+
const descriptor = Object.getOwnPropertyDescriptor(GeneratedClass.prototype, 'testFlag');
|
|
410
|
+
|
|
411
|
+
expect(descriptor).toBeDefined();
|
|
412
|
+
expect(typeof descriptor?.get).toBe('function');
|
|
413
|
+
expect(descriptor?.set).toBeUndefined();
|
|
414
|
+
expect(descriptor?.enumerable).toBe(false);
|
|
415
|
+
expect(descriptor?.configurable).toBe(true);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
test('no Proxy in generated class', () => {
|
|
419
|
+
const schema = defineFeatureFlags({
|
|
420
|
+
testFlag: S.boolean().default(false).sync(),
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
424
|
+
|
|
425
|
+
// Generated code should not contain Proxy
|
|
426
|
+
expect(code).not.toContain('new Proxy');
|
|
427
|
+
expect(code).not.toContain('Proxy(');
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
test('runtime path stays worker-safe', () => {
|
|
431
|
+
const schema = defineFeatureFlags({
|
|
432
|
+
testFlag: S.boolean().default(false).sync(),
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const GeneratedClass = createEvaluatorClass(
|
|
436
|
+
schema.schema,
|
|
437
|
+
(value, _schema, def) => value ?? def,
|
|
438
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
expect(() => GeneratedClass).not.toThrow();
|
|
442
|
+
expect(GeneratedClass.toString()).not.toContain('new Function');
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe('generateEvaluatorClass snapshots', () => {
|
|
448
|
+
test('snapshot: single boolean flag', () => {
|
|
449
|
+
const schema = defineFeatureFlags({
|
|
450
|
+
debugMode: S.boolean().default(false).sync(),
|
|
451
|
+
});
|
|
452
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
453
|
+
expect(code).toMatchSnapshot();
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test('snapshot: multiple flags of different types', () => {
|
|
457
|
+
const schema = defineFeatureFlags({
|
|
458
|
+
debugMode: S.boolean().default(false).sync(),
|
|
459
|
+
maxRetries: S.number().default(3).sync(),
|
|
460
|
+
logLevel: S.enum(['debug', 'info', 'warn', 'error'] as const)
|
|
461
|
+
.default('info')
|
|
462
|
+
.sync(),
|
|
463
|
+
});
|
|
464
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
465
|
+
expect(code).toMatchSnapshot();
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test('snapshot: async flags', () => {
|
|
469
|
+
const schema = defineFeatureFlags({
|
|
470
|
+
asyncFeature: S.boolean().default(false).async(),
|
|
471
|
+
asyncLimit: S.number().default(100).async(),
|
|
472
|
+
});
|
|
473
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
474
|
+
expect(code).toMatchSnapshot();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test('snapshot: custom class name', () => {
|
|
478
|
+
const schema = defineFeatureFlags({
|
|
479
|
+
testFlag: S.boolean().default(false).sync(),
|
|
480
|
+
});
|
|
481
|
+
const code = generateEvaluatorClass(schema.schema, 'CustomFeatureFlagEvaluator');
|
|
482
|
+
expect(code).toMatchSnapshot();
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
test('snapshot: many flags', () => {
|
|
486
|
+
const schema = defineFeatureFlags({
|
|
487
|
+
flag1: S.boolean().default(false).sync(),
|
|
488
|
+
flag2: S.boolean().default(true).sync(),
|
|
489
|
+
flag3: S.number().default(0).sync(),
|
|
490
|
+
flag4: S.number().default(100).sync(),
|
|
491
|
+
flag5: S.enum(['a', 'b', 'c'] as const)
|
|
492
|
+
.default('a')
|
|
493
|
+
.sync(),
|
|
494
|
+
});
|
|
495
|
+
const code = generateEvaluatorClass(schema.schema);
|
|
496
|
+
expect(code).toMatchSnapshot();
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Helper to count entries of a specific type in the buffer
|
|
502
|
+
*/
|
|
503
|
+
function countEntryType(buffer: AnySpanBuffer, entryType: number): number {
|
|
504
|
+
let count = 0;
|
|
505
|
+
let current: AnySpanBuffer | undefined = buffer;
|
|
506
|
+
while (current) {
|
|
507
|
+
const writeIndex = current._writeIndex;
|
|
508
|
+
for (let i = 0; i < writeIndex; i++) {
|
|
509
|
+
if (current.entry_type[i] === entryType) {
|
|
510
|
+
count++;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
current = current._overflow;
|
|
514
|
+
}
|
|
515
|
+
return count;
|
|
516
|
+
}
|