@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,404 @@
|
|
|
1
|
+
import type { Schema, SchemaWithMetadata } from '@smoothbricks/arrow-builder';
|
|
2
|
+
import { createEvaluatorClass, type GeneratedEvaluatorInstance } from '../codegen/evaluatorGenerator.js';
|
|
3
|
+
import type { FluentLogEntry } from '../codegen/spanLoggerGenerator.js';
|
|
4
|
+
import type { OpContext } from '../opContext/types.js';
|
|
5
|
+
import type { SpanContext } from '../spanContext.js';
|
|
6
|
+
import type { FeatureFlagSchema } from './defineFeatureFlags.js';
|
|
7
|
+
import type { LogSchema } from './LogSchema.js';
|
|
8
|
+
import { ENTRY_TYPE_FF_ACCESS } from './systemSchema.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Extended schema shape for flag validation — covers refine(), enum membership,
|
|
12
|
+
* SchemaType union.
|
|
13
|
+
*/
|
|
14
|
+
interface ExtendedFlagSchema extends Omit<SchemaWithMetadata, '__schema_type'> {
|
|
15
|
+
__schema_type?: string;
|
|
16
|
+
__refiner?: (value: unknown, fail: { fail(msg: string): never }) => unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Type guard to validate flag value matches schema.
|
|
21
|
+
* Uses __schema_type metadata for type-based validation instead of Sury.
|
|
22
|
+
*
|
|
23
|
+
* For feature flags the types are limited (string, number, boolean, enum, bigint).
|
|
24
|
+
* Schemas with __refiner (from refine()) invoke the refiner — on failure, return default.
|
|
25
|
+
* Schemas with __enum_values check membership.
|
|
26
|
+
*
|
|
27
|
+
* The runtime guard only knows the schema metadata, so the implementation returns
|
|
28
|
+
* `unknown` and lets the overloads carry the caller's concrete schema type.
|
|
29
|
+
*/
|
|
30
|
+
function validateFlagValue<T>(value: unknown, schema: Schema<T>, defaultValue: T): T;
|
|
31
|
+
function validateFlagValue(value: unknown, schema: Schema<unknown>, defaultValue: unknown): unknown {
|
|
32
|
+
const meta = schema as ExtendedFlagSchema;
|
|
33
|
+
|
|
34
|
+
// Handle refine() schemas — invoke the stored refiner, fall back to default on failure
|
|
35
|
+
if (meta.__refiner) {
|
|
36
|
+
try {
|
|
37
|
+
return meta.__refiner(value, {
|
|
38
|
+
fail(msg: string): never {
|
|
39
|
+
throw new Error(msg);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
} catch {
|
|
43
|
+
return defaultValue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
switch (meta.__schema_type) {
|
|
48
|
+
case 'number':
|
|
49
|
+
return typeof value === 'number' ? value : defaultValue;
|
|
50
|
+
case 'boolean':
|
|
51
|
+
return typeof value === 'boolean' ? value : defaultValue;
|
|
52
|
+
case 'text':
|
|
53
|
+
case 'category':
|
|
54
|
+
return typeof value === 'string' ? value : defaultValue;
|
|
55
|
+
case 'enum':
|
|
56
|
+
if (typeof value !== 'string') return defaultValue;
|
|
57
|
+
if (meta.__enum_values && !meta.__enum_values.includes(value)) return defaultValue;
|
|
58
|
+
return value;
|
|
59
|
+
case 'bigUint64':
|
|
60
|
+
return typeof value === 'bigint' ? value : defaultValue;
|
|
61
|
+
case 'key':
|
|
62
|
+
// Key schema in feature flags — validate it's a string
|
|
63
|
+
return typeof value === 'string' ? value : defaultValue;
|
|
64
|
+
default:
|
|
65
|
+
// Unknown schema type — reject by returning the default value.
|
|
66
|
+
// This prevents silently accepting invalid data for unhandled schema types.
|
|
67
|
+
return defaultValue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Serializable flag value types
|
|
73
|
+
*/
|
|
74
|
+
export type FlagValue = string | number | boolean | null;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* SpanContext without 'ff' field - prevents infinite recursion in evaluators
|
|
78
|
+
*/
|
|
79
|
+
export type SpanContextWithoutFf<Ctx extends OpContext> = Omit<SpanContext<Ctx>, 'ff'>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Feature flag evaluator interface (backend implementation)
|
|
83
|
+
*
|
|
84
|
+
* This is implemented by the backend (database, LaunchDarkly, etc.)
|
|
85
|
+
* and provides the actual flag values.
|
|
86
|
+
*
|
|
87
|
+
* ## Stateless Design - ctx is a parameter
|
|
88
|
+
*
|
|
89
|
+
* The evaluator receives `Omit<SpanContext, 'ff'>` as a PARAMETER (not stored state).
|
|
90
|
+
* This allows the evaluator to:
|
|
91
|
+
* - Be stateless (CAN be a singleton, but doesn't have to be)
|
|
92
|
+
* - Access full context (ctx.log, ctx.span, ctx.scope, ctx.deps, user properties)
|
|
93
|
+
* - Prevent infinite recursion (can't access ctx.ff which would call evaluator again)
|
|
94
|
+
*
|
|
95
|
+
* ## forContext() - Flexible Wrapper Creation
|
|
96
|
+
*
|
|
97
|
+
* The evaluator decides how to create the per-span wrapper:
|
|
98
|
+
* - Return a new wrapper with `this` as the evaluator (most common - reuse evaluator)
|
|
99
|
+
* - Return `this` if the evaluator itself implements the wrapper interface
|
|
100
|
+
* - Return a completely different evaluator/wrapper (e.g., per-span caching)
|
|
101
|
+
*
|
|
102
|
+
* The wrapper (FeatureFlagEvaluator) holds a ctx reference to enable fluent getters.
|
|
103
|
+
*
|
|
104
|
+
* @template Ctx - OpContext bundle (contains flags via Ctx['flags'])
|
|
105
|
+
*/
|
|
106
|
+
export interface FlagEvaluator<Ctx extends OpContext = OpContext> {
|
|
107
|
+
/**
|
|
108
|
+
* Get a flag value synchronously (for cached/static flags)
|
|
109
|
+
*
|
|
110
|
+
* The evaluator receives ctx as a parameter (stateless design).
|
|
111
|
+
* Can use ctx.log/ctx.span for tracing, ctx.scope for targeting.
|
|
112
|
+
*
|
|
113
|
+
* @param ctx - SpanContext without 'ff' (can log, create spans, access scope)
|
|
114
|
+
* @param flag - Flag name to evaluate
|
|
115
|
+
*/
|
|
116
|
+
getSync<K extends string>(ctx: SpanContextWithoutFf<Ctx>, flag: K): FlagValue;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get a flag value asynchronously (for dynamic flags)
|
|
120
|
+
*
|
|
121
|
+
* The evaluator receives ctx as a parameter (stateless design).
|
|
122
|
+
* Can use ctx.log/ctx.span for tracing external calls.
|
|
123
|
+
*
|
|
124
|
+
* @param ctx - SpanContext without 'ff' (can log, create spans, access scope)
|
|
125
|
+
* @param flag - Flag name to evaluate
|
|
126
|
+
*/
|
|
127
|
+
getAsync<K extends string>(ctx: SpanContextWithoutFf<Ctx>, flag: K): Promise<FlagValue>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Factory method: Create per-span wrapper from span context.
|
|
131
|
+
*
|
|
132
|
+
* Returns a FeatureFlagEvaluator (per-span wrapper) with typed getters for each flag.
|
|
133
|
+
*
|
|
134
|
+
* ## Implementation Choices
|
|
135
|
+
*
|
|
136
|
+
* Common pattern: Return a new wrapper that holds `this` as the evaluator
|
|
137
|
+
* ```typescript
|
|
138
|
+
* forContext(ctx) {
|
|
139
|
+
* return new FeatureFlagEvaluator(schema, ctx, this); // Reuse evaluator, new wrapper
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Alternative: Return `this` if evaluator implements the wrapper interface
|
|
144
|
+
* ```typescript
|
|
145
|
+
* forContext(ctx) {
|
|
146
|
+
* return this; // Evaluator itself is the wrapper (uncommon)
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* Alternative: Return different evaluator (e.g., per-span caching layer)
|
|
151
|
+
* ```typescript
|
|
152
|
+
* forContext(ctx) {
|
|
153
|
+
* return new CachedEvaluator(ctx, this); // Different wrapper with caching
|
|
154
|
+
* }
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* The wrapper MUST store ctx because JS getters (`get darkMode()`) cannot receive parameters.
|
|
158
|
+
*
|
|
159
|
+
* Receives `Omit<SpanContext, 'ff'>` to prevent infinite recursion.
|
|
160
|
+
*/
|
|
161
|
+
forContext(ctx: SpanContextWithoutFf<Ctx>): FeatureFlagEvaluator<Ctx> & InferFeatureFlagsWithContext<Ctx>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Column writers interface (to be implemented in buffer phase)
|
|
166
|
+
*
|
|
167
|
+
* Used for logging flag access and usage to span buffers.
|
|
168
|
+
*/
|
|
169
|
+
export interface FlagColumnWriters {
|
|
170
|
+
writeEntryType(type: 'ff-access' | 'ff-usage'): void;
|
|
171
|
+
writeFfName(name: string): void;
|
|
172
|
+
writeFfValue(value: FlagValue): void;
|
|
173
|
+
writeAction(action?: string): void;
|
|
174
|
+
writeOutcome(outcome?: string): void;
|
|
175
|
+
writeContextAttributes(context: Record<string, unknown>): void;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Flag Context Types - returned when flag is enabled
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Track context for feature flag usage analytics
|
|
184
|
+
*/
|
|
185
|
+
export interface FlagTrackContext {
|
|
186
|
+
action?: string;
|
|
187
|
+
outcome?: string;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Boolean flag context - returned when boolean flag is true
|
|
192
|
+
*/
|
|
193
|
+
export interface BooleanFlagContext<TLog extends LogSchema = LogSchema> {
|
|
194
|
+
readonly value: true;
|
|
195
|
+
track(context?: FlagTrackContext): FluentLogEntry<TLog>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Variant flag context - returned when variant flag is enabled
|
|
200
|
+
*/
|
|
201
|
+
export interface VariantFlagContext<V extends string, TLog extends LogSchema = LogSchema> {
|
|
202
|
+
readonly value: V;
|
|
203
|
+
track(context?: FlagTrackContext): FluentLogEntry<TLog>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Config flag context - returned when config flag is enabled
|
|
208
|
+
* Spreads the config object and adds track() method
|
|
209
|
+
*/
|
|
210
|
+
export type ConfigFlagContext<T extends Record<string, unknown>, TLog extends LogSchema = LogSchema> = T & {
|
|
211
|
+
track(context?: FlagTrackContext): FluentLogEntry<TLog>;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// Type Inference for Feature Flags
|
|
216
|
+
// ============================================================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Infer the flag context type for a single flag definition
|
|
220
|
+
*/
|
|
221
|
+
type InferFlagContextType<Ctx extends OpContext, T> = T extends boolean
|
|
222
|
+
? BooleanFlagContext<Ctx['logSchema']>
|
|
223
|
+
: T extends string
|
|
224
|
+
? VariantFlagContext<T, Ctx['logSchema']>
|
|
225
|
+
: T extends Record<string, unknown>
|
|
226
|
+
? ConfigFlagContext<T, Ctx['logSchema']>
|
|
227
|
+
: { value: T; track(context?: FlagTrackContext): FluentLogEntry<Ctx['logSchema']> };
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Infer feature flag types from OpContext - returns FlagContext | undefined for each flag
|
|
231
|
+
*
|
|
232
|
+
* - Returns undefined when flag is false/disabled
|
|
233
|
+
* - Returns FlagContext wrapper when flag is truthy/enabled
|
|
234
|
+
*/
|
|
235
|
+
export type InferFeatureFlagsWithContext<Ctx extends OpContext> = Ctx['flags'] extends FeatureFlagSchema
|
|
236
|
+
? {
|
|
237
|
+
readonly [K in keyof Ctx['flags']]:
|
|
238
|
+
| InferFlagContextType<Ctx, import('@smoothbricks/arrow-builder').Output<Ctx['flags'][K]['schema']>>
|
|
239
|
+
| undefined;
|
|
240
|
+
}
|
|
241
|
+
: Record<string, never>;
|
|
242
|
+
|
|
243
|
+
// ============================================================================
|
|
244
|
+
// Feature Flag Evaluator Class
|
|
245
|
+
// ============================================================================
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get or create a generated evaluator class for a schema.
|
|
249
|
+
*
|
|
250
|
+
* The worker-safe constructor cache lives in `evaluatorGenerator.ts`.
|
|
251
|
+
*/
|
|
252
|
+
function getOrCreateEvaluatorClass<Ctx extends OpContext>(
|
|
253
|
+
schema: Ctx['flags'],
|
|
254
|
+
): new (
|
|
255
|
+
spanContext: SpanContextWithoutFf<Ctx>,
|
|
256
|
+
evaluator: FlagEvaluator<Ctx>,
|
|
257
|
+
) => GeneratedEvaluatorInstance<Ctx> {
|
|
258
|
+
return createEvaluatorClass(schema, validateFlagValue, ENTRY_TYPE_FF_ACCESS);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Feature flag evaluator with undefined/truthy semantics (PER-SPAN WRAPPER)
|
|
263
|
+
*
|
|
264
|
+
* ## Architecture: Stateless Evaluator + Per-Span Wrapper
|
|
265
|
+
*
|
|
266
|
+
* ```
|
|
267
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
268
|
+
* │ FlagEvaluator (backend - CAN be singleton) │
|
|
269
|
+
* │ - getSync(ctx, flag) → FlagValue │
|
|
270
|
+
* │ - getAsync(ctx, flag) → Promise<FlagValue> │
|
|
271
|
+
* │ - forContext(ctx) → new FeatureFlagEvaluator(ctx, this) │
|
|
272
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
273
|
+
* ▲
|
|
274
|
+
* │ reference (can be reused or new)
|
|
275
|
+
* │
|
|
276
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
277
|
+
* │ FeatureFlagEvaluator (PER-SPAN - holds ctx reference) │
|
|
278
|
+
* │ #spanContext = ctx │
|
|
279
|
+
* │ #evaluator = backend evaluator │
|
|
280
|
+
* │ │
|
|
281
|
+
* │ get darkMode() { │
|
|
282
|
+
* │ return this.#getFlag('darkMode'); │
|
|
283
|
+
* │ // calls this.#evaluator.getSync(this.#spanContext, 'x') │
|
|
284
|
+
* │ } │
|
|
285
|
+
* │ │
|
|
286
|
+
* │ forContext(childCtx) { │
|
|
287
|
+
* │ // Reuse same evaluator, new wrapper with childCtx │
|
|
288
|
+
* │ return new FeatureFlagEvaluator(childCtx, this.#evaluator)│
|
|
289
|
+
* │ } │
|
|
290
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* ## Why Per-Span Wrapper?
|
|
294
|
+
*
|
|
295
|
+
* JS getters (`get darkMode()`) cannot receive parameters. To provide the fluent
|
|
296
|
+
* API `ctx.ff.darkMode`, we need to store the ctx reference in the wrapper instance.
|
|
297
|
+
*
|
|
298
|
+
* The backend evaluator (FlagEvaluator) receives ctx as a parameter, so it CAN be
|
|
299
|
+
* stateless/singleton. The wrapper is created per-span to bind ctx to getters.
|
|
300
|
+
*
|
|
301
|
+
* ## Behavior
|
|
302
|
+
*
|
|
303
|
+
* - Returns undefined when flag is false/disabled
|
|
304
|
+
* - Returns FlagContext wrapper when flag is truthy/enabled
|
|
305
|
+
* - First access logs ff-access entry
|
|
306
|
+
* - Subsequent access in same span returns cached value (no duplicate log)
|
|
307
|
+
* - track() always logs ff-usage entry
|
|
308
|
+
*
|
|
309
|
+
* ## V8 Optimization Benefits
|
|
310
|
+
*
|
|
311
|
+
* - Stable hidden class (all instances have same shape)
|
|
312
|
+
* - Monomorphic property access (getters are real properties)
|
|
313
|
+
* - No Proxy trap overhead
|
|
314
|
+
* - Inline caching works properly
|
|
315
|
+
*
|
|
316
|
+
* ## Generated Class Pattern
|
|
317
|
+
*
|
|
318
|
+
* The class constructor returns a generated class instance rather than this instance.
|
|
319
|
+
* This is a valid JavaScript pattern for creating optimized instances with schema-specific properties.
|
|
320
|
+
*
|
|
321
|
+
* @template Ctx - OpContext bundle (contains flags via Ctx['flags'])
|
|
322
|
+
*/
|
|
323
|
+
export abstract class FeatureFlagEvaluator<Ctx extends OpContext = OpContext> {
|
|
324
|
+
/**
|
|
325
|
+
* Get async flag value
|
|
326
|
+
* Returns undefined when false, FlagContext when truthy
|
|
327
|
+
*/
|
|
328
|
+
abstract get<K extends keyof InferFeatureFlagsWithContext<Ctx> & string>(
|
|
329
|
+
flag: K,
|
|
330
|
+
): Promise<InferFeatureFlagsWithContext<Ctx>[K]>;
|
|
331
|
+
abstract get(flag: string): Promise<unknown>;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Create a new wrapper for a child span context.
|
|
335
|
+
*
|
|
336
|
+
* The implementation can reuse the same evaluator (singleton pattern),
|
|
337
|
+
* create a new evaluator, or return `this` if the evaluator itself
|
|
338
|
+
* implements the wrapper interface.
|
|
339
|
+
*/
|
|
340
|
+
abstract forContext(ctx: SpanContext<Ctx>): FeatureFlagEvaluator<Ctx> & InferFeatureFlagsWithContext<Ctx>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Create a FeatureFlagEvaluator instance using the generated class
|
|
345
|
+
*/
|
|
346
|
+
export function createFeatureFlagEvaluator<Ctx extends OpContext>(
|
|
347
|
+
schema: Ctx['flags'],
|
|
348
|
+
spanContext: SpanContextWithoutFf<Ctx>,
|
|
349
|
+
evaluator: FlagEvaluator<Ctx>,
|
|
350
|
+
): FeatureFlagEvaluator<Ctx> & InferFeatureFlagsWithContext<Ctx> {
|
|
351
|
+
const GeneratedClass = getOrCreateEvaluatorClass<Ctx>(schema);
|
|
352
|
+
const instance: GeneratedEvaluatorInstance<Ctx> = new GeneratedClass(spanContext, evaluator);
|
|
353
|
+
return instance;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Simple in-memory flag evaluator for testing
|
|
358
|
+
*
|
|
359
|
+
* Demonstrates the simplest evaluator pattern:
|
|
360
|
+
* - getSync/getAsync receive ctx first, enabling evaluators to use ctx.log, ctx.scope
|
|
361
|
+
* - forContext bootstraps the generated FeatureFlagEvaluator class (creates per-span wrapper)
|
|
362
|
+
* - Generated class has typed getters (ff.darkMode) and calls this.getSync(ctx, flag)
|
|
363
|
+
*/
|
|
364
|
+
export class InMemoryFlagEvaluator<Ctx extends OpContext = OpContext> implements FlagEvaluator<Ctx> {
|
|
365
|
+
private flags: Record<string, FlagValue> = {};
|
|
366
|
+
private ffSchema: Ctx['flags'];
|
|
367
|
+
|
|
368
|
+
constructor(ffSchema: Ctx['flags'], initialFlags: Record<string, FlagValue> = {}) {
|
|
369
|
+
this.ffSchema = ffSchema;
|
|
370
|
+
this.flags = initialFlags;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Get flag value synchronously.
|
|
375
|
+
* Simple evaluator ignores ctx - just returns stored value.
|
|
376
|
+
* Advanced evaluators can use ctx.log, ctx.span, ctx.scope, etc.
|
|
377
|
+
*/
|
|
378
|
+
getSync<K extends string>(_ctx: SpanContextWithoutFf<Ctx>, flag: K): FlagValue {
|
|
379
|
+
return this.flags[flag] ?? null;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get flag value asynchronously.
|
|
384
|
+
* Simple evaluator ignores ctx - just returns stored value.
|
|
385
|
+
* Advanced evaluators can use ctx.log, ctx.span for tracing external calls.
|
|
386
|
+
*/
|
|
387
|
+
async getAsync<K extends string>(_ctx: SpanContextWithoutFf<Ctx>, flag: K): Promise<FlagValue> {
|
|
388
|
+
return this.flags[flag] ?? null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
setFlag(flag: string, value: FlagValue): void {
|
|
392
|
+
this.flags[flag] = value;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Create span-bound FeatureFlagEvaluator with typed getters.
|
|
397
|
+
*
|
|
398
|
+
* Returns a per-span wrapper that holds ctx reference and reuses this evaluator.
|
|
399
|
+
* The generated class has typed getters (ff.darkMode) and calls this.getSync(ctx, flag).
|
|
400
|
+
*/
|
|
401
|
+
forContext(ctx: SpanContextWithoutFf<Ctx>): FeatureFlagEvaluator<Ctx> & InferFeatureFlagsWithContext<Ctx> {
|
|
402
|
+
return createFeatureFlagEvaluator(this.ffSchema, ctx, this);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema extension utilities for composing tag attribute schemas
|
|
3
|
+
*
|
|
4
|
+
* This enables building complex schemas from smaller, reusable pieces:
|
|
5
|
+
* - Base attributes (requestId, userId, etc.)
|
|
6
|
+
* - HTTP-specific attributes (httpStatus, httpMethod, etc.)
|
|
7
|
+
* - Database-specific attributes (dbQuery, dbDuration, etc.)
|
|
8
|
+
* - Custom domain attributes
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { LogSchema } from './LogSchema.js';
|
|
12
|
+
import type { SchemaFields } from './types.js';
|
|
13
|
+
|
|
14
|
+
export function extendSchema<T extends SchemaFields, U extends SchemaFields>(
|
|
15
|
+
base: LogSchema<T>,
|
|
16
|
+
extension: U,
|
|
17
|
+
): LogSchema<T & U>;
|
|
18
|
+
export function extendSchema<T extends SchemaFields, U extends SchemaFields>(base: T, extension: U): T & U;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Merge two log schemas with conflict detection
|
|
22
|
+
*
|
|
23
|
+
* This performs shallow merge and validates:
|
|
24
|
+
* - No conflicting field names
|
|
25
|
+
* - No reserved names in extension
|
|
26
|
+
*
|
|
27
|
+
* Example:
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const base = { requestId: S.category() };
|
|
30
|
+
* const httpAttrs = { httpStatus: S.number(), httpMethod: S.enum(['GET', 'POST']) };
|
|
31
|
+
* const combined = extendSchema(base, httpAttrs);
|
|
32
|
+
* // Result: { requestId, httpStatus, httpMethod }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @param base - Base log schema (LogSchema or plain object)
|
|
36
|
+
* @param extension - Additional attributes to add
|
|
37
|
+
* @returns Merged schema
|
|
38
|
+
* @throws Error if field names conflict
|
|
39
|
+
*/
|
|
40
|
+
export function extendSchema<U extends SchemaFields>(
|
|
41
|
+
base: LogSchema | SchemaFields,
|
|
42
|
+
extension: U,
|
|
43
|
+
): LogSchema | SchemaFields {
|
|
44
|
+
// Extract base fields (from LogSchema.fields or plain object)
|
|
45
|
+
const baseFields = base instanceof LogSchema ? base.fields : base;
|
|
46
|
+
const baseKeys = new Set(Object.keys(baseFields));
|
|
47
|
+
|
|
48
|
+
// Check for field name conflicts
|
|
49
|
+
for (const key of Object.keys(extension)) {
|
|
50
|
+
if (baseKeys.has(key)) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Schema conflict: attribute '${key}' already exists in base schema. ` +
|
|
53
|
+
`Base schema has: ${Object.keys(baseFields).join(', ')}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Assert extension doesn't use reserved names
|
|
59
|
+
LogSchema.assertUserFieldNames(Object.keys(extension));
|
|
60
|
+
|
|
61
|
+
// Perform shallow merge
|
|
62
|
+
const merged = { ...baseFields, ...extension };
|
|
63
|
+
|
|
64
|
+
// If base was LogSchema, return LogSchema; otherwise return plain object
|
|
65
|
+
if (base instanceof LogSchema) {
|
|
66
|
+
return new LogSchema(merged);
|
|
67
|
+
}
|
|
68
|
+
return merged;
|
|
69
|
+
}
|