dotdo 0.0.1 → 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/LICENSE +1 -1
- package/README.md +446 -315
- package/cli/README.md +238 -0
- package/cli/agent.ts +72 -0
- package/cli/bin.js +44 -0
- package/cli/bin.ts +38 -0
- package/cli/build.ts +157 -0
- package/cli/commands/auth/login.ts +14 -0
- package/cli/commands/auth/logout.ts +6 -0
- package/cli/commands/auth/whoami.ts +16 -0
- package/cli/commands/deploy-multi.ts +245 -0
- package/cli/commands/dev/deploy.ts +100 -0
- package/cli/commands/dev/dev.ts +95 -0
- package/cli/commands/dev/logs.ts +91 -0
- package/cli/commands/dev-local.ts +88 -0
- package/cli/commands/do-ops.ts +314 -0
- package/cli/commands/index.ts +100 -0
- package/cli/commands/init.ts +247 -0
- package/cli/commands/introspect/emitter.ts +315 -0
- package/cli/commands/introspect/index.ts +193 -0
- package/cli/commands/link.ts +598 -0
- package/cli/commands/snippets.ts +415 -0
- package/cli/commands/tunnel.ts +239 -0
- package/cli/device-auth.ts +289 -0
- package/cli/fallback.ts +12 -0
- package/cli/index.ts +121 -0
- package/cli/main.ts +246 -0
- package/cli/mcp-stdio.ts +790 -0
- package/cli/package.json +62 -0
- package/cli/runtime/do-registry.ts +193 -0
- package/cli/runtime/embedded-db.ts +344 -0
- package/cli/runtime/index.ts +9 -0
- package/cli/runtime/miniflare-adapter.ts +162 -0
- package/cli/sandbox.ts +82 -0
- package/cli/src/args.ts +174 -0
- package/cli/src/auth.ts +55 -0
- package/cli/src/commands/call.ts +84 -0
- package/cli/src/commands/charge.ts +96 -0
- package/cli/src/commands/config.ts +115 -0
- package/cli/src/commands/email.ts +112 -0
- package/cli/src/commands/llm.ts +115 -0
- package/cli/src/commands/queue.ts +134 -0
- package/cli/src/commands/text.ts +86 -0
- package/cli/src/config.ts +185 -0
- package/cli/src/output.ts +246 -0
- package/cli/src/rpc.ts +192 -0
- package/cli/utils/config.ts +282 -0
- package/cli/utils/detect.ts +73 -0
- package/cli/utils/index.ts +15 -0
- package/cli/utils/logger.ts +232 -0
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/template-literals.js +852 -0
- package/dist/ai/template-literals.js.map +1 -0
- package/dist/api/middleware/auth-federation.js +573 -0
- package/dist/api/middleware/auth-federation.js.map +1 -0
- package/dist/api/middleware/auth.js +545 -0
- package/dist/api/middleware/auth.js.map +1 -0
- package/dist/db/actions.js +212 -0
- package/dist/db/actions.js.map +1 -0
- package/dist/db/auth.js +506 -0
- package/dist/db/auth.js.map +1 -0
- package/dist/db/branches.js +65 -0
- package/dist/db/branches.js.map +1 -0
- package/dist/db/clickhouse.js +1074 -0
- package/dist/db/clickhouse.js.map +1 -0
- package/dist/db/dlq.js +39 -0
- package/dist/db/dlq.js.map +1 -0
- package/dist/db/events.js +28 -0
- package/dist/db/events.js.map +1 -0
- package/dist/db/exec.js +64 -0
- package/dist/db/exec.js.map +1 -0
- package/dist/db/files.js +85 -0
- package/dist/db/files.js.map +1 -0
- package/dist/db/flags.js +24 -0
- package/dist/db/flags.js.map +1 -0
- package/dist/db/git.js +116 -0
- package/dist/db/git.js.map +1 -0
- package/dist/db/iceberg/inverted-index.js +862 -0
- package/dist/db/iceberg/inverted-index.js.map +1 -0
- package/dist/db/iceberg/puffin.js +878 -0
- package/dist/db/iceberg/puffin.js.map +1 -0
- package/dist/db/iceberg/search-manifest.js +422 -0
- package/dist/db/iceberg/search-manifest.js.map +1 -0
- package/dist/db/iceberg/types.js +8 -0
- package/dist/db/iceberg/types.js.map +1 -0
- package/dist/db/index.js +121 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/integrations.js +368 -0
- package/dist/db/integrations.js.map +1 -0
- package/dist/db/json-indexes.js +332 -0
- package/dist/db/json-indexes.js.map +1 -0
- package/dist/db/linked-accounts.js +287 -0
- package/dist/db/linked-accounts.js.map +1 -0
- package/dist/db/nouns.js +183 -0
- package/dist/db/nouns.js.map +1 -0
- package/dist/db/objects.js +170 -0
- package/dist/db/objects.js.map +1 -0
- package/dist/db/primitives/dag-scheduler/index.js +869 -0
- package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
- package/dist/db/primitives/exactly-once-context.js +237 -0
- package/dist/db/primitives/exactly-once-context.js.map +1 -0
- package/dist/db/primitives/index.js +62 -0
- package/dist/db/primitives/index.js.map +1 -0
- package/dist/db/primitives/keyed-router.js +145 -0
- package/dist/db/primitives/keyed-router.js.map +1 -0
- package/dist/db/primitives/observability.js +162 -0
- package/dist/db/primitives/observability.js.map +1 -0
- package/dist/db/primitives/schema-evolution.js +643 -0
- package/dist/db/primitives/schema-evolution.js.map +1 -0
- package/dist/db/primitives/stateful-operator/index.js +770 -0
- package/dist/db/primitives/stateful-operator/index.js.map +1 -0
- package/dist/db/primitives/temporal-store.js +306 -0
- package/dist/db/primitives/temporal-store.js.map +1 -0
- package/dist/db/primitives/typed-column-store.js +1229 -0
- package/dist/db/primitives/typed-column-store.js.map +1 -0
- package/dist/db/primitives/utils/duration.js +162 -0
- package/dist/db/primitives/utils/duration.js.map +1 -0
- package/dist/db/primitives/utils/murmur3.js +116 -0
- package/dist/db/primitives/utils/murmur3.js.map +1 -0
- package/dist/db/primitives/watermark-service.js +136 -0
- package/dist/db/primitives/watermark-service.js.map +1 -0
- package/dist/db/primitives/window-manager.js +764 -0
- package/dist/db/primitives/window-manager.js.map +1 -0
- package/dist/db/relationships.js +66 -0
- package/dist/db/relationships.js.map +1 -0
- package/dist/db/schema-minimal.js +61 -0
- package/dist/db/schema-minimal.js.map +1 -0
- package/dist/db/search.js +28 -0
- package/dist/db/search.js.map +1 -0
- package/dist/db/stores.js +1665 -0
- package/dist/db/stores.js.map +1 -0
- package/dist/db/things.js +297 -0
- package/dist/db/things.js.map +1 -0
- package/dist/db/vault.js +171 -0
- package/dist/db/vault.js.map +1 -0
- package/dist/db/verbs.js +102 -0
- package/dist/db/verbs.js.map +1 -0
- package/dist/do/base.js +48 -0
- package/dist/do/base.js.map +1 -0
- package/dist/do/tiny.js +31 -0
- package/dist/do/tiny.js.map +1 -0
- package/dist/lib/DOAuth.js +261 -0
- package/dist/lib/DOAuth.js.map +1 -0
- package/dist/lib/DODispatcher.js +72 -0
- package/dist/lib/DODispatcher.js.map +1 -0
- package/dist/lib/Modifier.js +189 -0
- package/dist/lib/Modifier.js.map +1 -0
- package/dist/lib/StateStorage.js +403 -0
- package/dist/lib/StateStorage.js.map +1 -0
- package/dist/lib/TypeRegistry.js +122 -0
- package/dist/lib/TypeRegistry.js.map +1 -0
- package/dist/lib/ai/gateway.js +247 -0
- package/dist/lib/ai/gateway.js.map +1 -0
- package/dist/lib/ai/tool-loop-agent.js +591 -0
- package/dist/lib/ai/tool-loop-agent.js.map +1 -0
- package/dist/lib/auto-wiring.js +439 -0
- package/dist/lib/auto-wiring.js.map +1 -0
- package/dist/lib/browse/browserbase.js +163 -0
- package/dist/lib/browse/browserbase.js.map +1 -0
- package/dist/lib/browse/cloudflare.js +144 -0
- package/dist/lib/browse/cloudflare.js.map +1 -0
- package/dist/lib/browse/index.js +62 -0
- package/dist/lib/browse/index.js.map +1 -0
- package/dist/lib/browse/types.js +13 -0
- package/dist/lib/browse/types.js.map +1 -0
- package/dist/lib/cache/index.js +37 -0
- package/dist/lib/cache/index.js.map +1 -0
- package/dist/lib/cache/visibility.js +638 -0
- package/dist/lib/cache/visibility.js.map +1 -0
- package/dist/lib/capabilities.js +268 -0
- package/dist/lib/capabilities.js.map +1 -0
- package/dist/lib/channels/base.js +106 -0
- package/dist/lib/channels/base.js.map +1 -0
- package/dist/lib/channels/discord.js +94 -0
- package/dist/lib/channels/discord.js.map +1 -0
- package/dist/lib/channels/email.js +204 -0
- package/dist/lib/channels/email.js.map +1 -0
- package/dist/lib/channels/index.js +90 -0
- package/dist/lib/channels/index.js.map +1 -0
- package/dist/lib/channels/mdxui-chat.js +95 -0
- package/dist/lib/channels/mdxui-chat.js.map +1 -0
- package/dist/lib/channels/slack-blockkit.js +121 -0
- package/dist/lib/channels/slack-blockkit.js.map +1 -0
- package/dist/lib/channels/types.js +7 -0
- package/dist/lib/channels/types.js.map +1 -0
- package/dist/lib/cloudflare/ai.js +654 -0
- package/dist/lib/cloudflare/ai.js.map +1 -0
- package/dist/lib/cloudflare/index.js +88 -0
- package/dist/lib/cloudflare/index.js.map +1 -0
- package/dist/lib/cloudflare/kv.js +342 -0
- package/dist/lib/cloudflare/kv.js.map +1 -0
- package/dist/lib/cloudflare/queues.js +434 -0
- package/dist/lib/cloudflare/queues.js.map +1 -0
- package/dist/lib/cloudflare/r2.js +604 -0
- package/dist/lib/cloudflare/r2.js.map +1 -0
- package/dist/lib/cloudflare/vectorize.js +494 -0
- package/dist/lib/cloudflare/vectorize.js.map +1 -0
- package/dist/lib/cloudflare/workflows.js +569 -0
- package/dist/lib/cloudflare/workflows.js.map +1 -0
- package/dist/lib/colo/caching.js +196 -0
- package/dist/lib/colo/caching.js.map +1 -0
- package/dist/lib/colo/detection.js +194 -0
- package/dist/lib/colo/detection.js.map +1 -0
- package/dist/lib/colo/external-data.js +219 -0
- package/dist/lib/colo/external-data.js.map +1 -0
- package/dist/lib/colo/globe-data.js +179 -0
- package/dist/lib/colo/globe-data.js.map +1 -0
- package/dist/lib/colo/index.js +16 -0
- package/dist/lib/colo/index.js.map +1 -0
- package/dist/lib/decorators.js +37 -0
- package/dist/lib/decorators.js.map +1 -0
- package/dist/lib/discovery.js +81 -0
- package/dist/lib/discovery.js.map +1 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
- package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/CascadeExecutor.js +418 -0
- package/dist/lib/executors/CascadeExecutor.js.map +1 -0
- package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
- package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
- package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/ParallelStepExecutor.js +308 -0
- package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
- package/dist/lib/executors/types.js +12 -0
- package/dist/lib/executors/types.js.map +1 -0
- package/dist/lib/experiments.js +89 -0
- package/dist/lib/experiments.js.map +1 -0
- package/dist/lib/flags/store.js +262 -0
- package/dist/lib/flags/store.js.map +1 -0
- package/dist/lib/functions/FunctionComposition.js +467 -0
- package/dist/lib/functions/FunctionComposition.js.map +1 -0
- package/dist/lib/functions/FunctionMiddleware.js +457 -0
- package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
- package/dist/lib/functions/FunctionRegistry.js +426 -0
- package/dist/lib/functions/FunctionRegistry.js.map +1 -0
- package/dist/lib/functions/createFunction.js +1048 -0
- package/dist/lib/functions/createFunction.js.map +1 -0
- package/dist/lib/humans/index.js +68 -0
- package/dist/lib/humans/index.js.map +1 -0
- package/dist/lib/humans/templates.js +117 -0
- package/dist/lib/humans/templates.js.map +1 -0
- package/dist/lib/identity.js +98 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/logging/error-logger.js +163 -0
- package/dist/lib/logging/error-logger.js.map +1 -0
- package/dist/lib/logging/index.js +160 -0
- package/dist/lib/logging/index.js.map +1 -0
- package/dist/lib/mixins/bash.js +753 -0
- package/dist/lib/mixins/bash.js.map +1 -0
- package/dist/lib/mixins/fs.js +648 -0
- package/dist/lib/mixins/fs.js.map +1 -0
- package/dist/lib/mixins/git.js +1006 -0
- package/dist/lib/mixins/git.js.map +1 -0
- package/dist/lib/mixins/npm.js +662 -0
- package/dist/lib/mixins/npm.js.map +1 -0
- package/dist/lib/noun-id.js +278 -0
- package/dist/lib/noun-id.js.map +1 -0
- package/dist/lib/rate-limit/sliding-window.js +148 -0
- package/dist/lib/rate-limit/sliding-window.js.map +1 -0
- package/dist/lib/rate-limit.js +110 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/rpc/bindings.js +548 -0
- package/dist/lib/rpc/bindings.js.map +1 -0
- package/dist/lib/rpc/index.js +64 -0
- package/dist/lib/rpc/index.js.map +1 -0
- package/dist/lib/safe-stringify.js +223 -0
- package/dist/lib/safe-stringify.js.map +1 -0
- package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
- package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
- package/dist/lib/sqids.js +110 -0
- package/dist/lib/sqids.js.map +1 -0
- package/dist/lib/sql/adapters/index.js +10 -0
- package/dist/lib/sql/adapters/index.js.map +1 -0
- package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
- package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
- package/dist/lib/sql/adapters/pgsql-parser.js +1190 -0
- package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
- package/dist/lib/sql/index.js +277 -0
- package/dist/lib/sql/index.js.map +1 -0
- package/dist/lib/sql/types.js +56 -0
- package/dist/lib/sql/types.js.map +1 -0
- package/dist/lib/type-classifier.js +126 -0
- package/dist/lib/type-classifier.js.map +1 -0
- package/dist/lib/utils/html.js +47 -0
- package/dist/lib/utils/html.js.map +1 -0
- package/dist/lib/validation.js +48 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/lib/vault/store.js +411 -0
- package/dist/lib/vault/store.js.map +1 -0
- package/dist/metrics/hunch.js +739 -0
- package/dist/metrics/hunch.js.map +1 -0
- package/dist/objects/API.js +302 -0
- package/dist/objects/API.js.map +1 -0
- package/dist/objects/Agent.js +179 -0
- package/dist/objects/Agent.js.map +1 -0
- package/dist/objects/AgenticFunctionExecutor.js +8 -0
- package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
- package/dist/objects/App.js +83 -0
- package/dist/objects/App.js.map +1 -0
- package/dist/objects/Browser.js +884 -0
- package/dist/objects/Browser.js.map +1 -0
- package/dist/objects/Business.js +107 -0
- package/dist/objects/Business.js.map +1 -0
- package/dist/objects/CLI.js +221 -0
- package/dist/objects/CLI.js.map +1 -0
- package/dist/objects/CodeFunctionExecutor.js +8 -0
- package/dist/objects/CodeFunctionExecutor.js.map +1 -0
- package/dist/objects/Collection.js +161 -0
- package/dist/objects/Collection.js.map +1 -0
- package/dist/objects/DO.js +41 -0
- package/dist/objects/DO.js.map +1 -0
- package/dist/objects/DOBase.js +2309 -0
- package/dist/objects/DOBase.js.map +1 -0
- package/dist/objects/DOCache.js +153 -0
- package/dist/objects/DOCache.js.map +1 -0
- package/dist/objects/DOFull.js +1676 -0
- package/dist/objects/DOFull.js.map +1 -0
- package/dist/objects/DOTiny.js +207 -0
- package/dist/objects/DOTiny.js.map +1 -0
- package/dist/objects/Directory.js +199 -0
- package/dist/objects/Directory.js.map +1 -0
- package/dist/objects/Entity.js +413 -0
- package/dist/objects/Entity.js.map +1 -0
- package/dist/objects/Function.js +116 -0
- package/dist/objects/Function.js.map +1 -0
- package/dist/objects/Human.js +231 -0
- package/dist/objects/Human.js.map +1 -0
- package/dist/objects/HumanFunctionExecutor.js +8 -0
- package/dist/objects/HumanFunctionExecutor.js.map +1 -0
- package/dist/objects/IcebergMetadataDO.js +938 -0
- package/dist/objects/IcebergMetadataDO.js.map +1 -0
- package/dist/objects/IntegrationsDO.js +1174 -0
- package/dist/objects/IntegrationsDO.js.map +1 -0
- package/dist/objects/ObservabilityBroadcaster.js +149 -0
- package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
- package/dist/objects/Package.js +154 -0
- package/dist/objects/Package.js.map +1 -0
- package/dist/objects/Product.js +193 -0
- package/dist/objects/Product.js.map +1 -0
- package/dist/objects/SDK.js +152 -0
- package/dist/objects/SDK.js.map +1 -0
- package/dist/objects/SaaS.js +235 -0
- package/dist/objects/SaaS.js.map +1 -0
- package/dist/objects/SandboxDO.js +759 -0
- package/dist/objects/SandboxDO.js.map +1 -0
- package/dist/objects/Service.js +337 -0
- package/dist/objects/Service.js.map +1 -0
- package/dist/objects/Site.js +80 -0
- package/dist/objects/Site.js.map +1 -0
- package/dist/objects/Startup.js +479 -0
- package/dist/objects/Startup.js.map +1 -0
- package/dist/objects/ThingsDO.js +170 -0
- package/dist/objects/ThingsDO.js.map +1 -0
- package/dist/objects/VectorShardDO.js +650 -0
- package/dist/objects/VectorShardDO.js.map +1 -0
- package/dist/objects/Worker.js +144 -0
- package/dist/objects/Worker.js.map +1 -0
- package/dist/objects/Workflow.js +196 -0
- package/dist/objects/Workflow.js.map +1 -0
- package/dist/objects/WorkflowFactory.js +313 -0
- package/dist/objects/WorkflowFactory.js.map +1 -0
- package/dist/objects/WorkflowRuntime.js +863 -0
- package/dist/objects/WorkflowRuntime.js.map +1 -0
- package/dist/objects/circuit-breaker-bulkhead.js +178 -0
- package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
- package/dist/objects/createFunction.js +934 -0
- package/dist/objects/createFunction.js.map +1 -0
- package/dist/objects/index.js +80 -0
- package/dist/objects/index.js.map +1 -0
- package/dist/objects/lifecycle/Branch.js +275 -0
- package/dist/objects/lifecycle/Branch.js.map +1 -0
- package/dist/objects/lifecycle/Clone.js +1499 -0
- package/dist/objects/lifecycle/Clone.js.map +1 -0
- package/dist/objects/lifecycle/Compact.js +237 -0
- package/dist/objects/lifecycle/Compact.js.map +1 -0
- package/dist/objects/lifecycle/Promote.js +476 -0
- package/dist/objects/lifecycle/Promote.js.map +1 -0
- package/dist/objects/lifecycle/Shard.js +560 -0
- package/dist/objects/lifecycle/Shard.js.map +1 -0
- package/dist/objects/lifecycle/index.js +15 -0
- package/dist/objects/lifecycle/index.js.map +1 -0
- package/dist/objects/lifecycle/types.js +33 -0
- package/dist/objects/lifecycle/types.js.map +1 -0
- package/dist/objects/mixins/infrastructure.js +171 -0
- package/dist/objects/mixins/infrastructure.js.map +1 -0
- package/dist/objects/modules/StoresModule.js +153 -0
- package/dist/objects/modules/StoresModule.js.map +1 -0
- package/dist/objects/persistence/checkpoint-manager.js +606 -0
- package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
- package/dist/objects/persistence/index.js +72 -0
- package/dist/objects/persistence/index.js.map +1 -0
- package/dist/objects/persistence/migration-runner.js +562 -0
- package/dist/objects/persistence/migration-runner.js.map +1 -0
- package/dist/objects/persistence/replication-manager.js +501 -0
- package/dist/objects/persistence/replication-manager.js.map +1 -0
- package/dist/objects/persistence/tiered-storage-manager.js +595 -0
- package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
- package/dist/objects/persistence/types.js +14 -0
- package/dist/objects/persistence/types.js.map +1 -0
- package/dist/objects/persistence/wal-manager.js +653 -0
- package/dist/objects/persistence/wal-manager.js.map +1 -0
- package/dist/objects/presets/index.js +20 -0
- package/dist/objects/presets/index.js.map +1 -0
- package/dist/objects/presets/primitives.js +188 -0
- package/dist/objects/presets/primitives.js.map +1 -0
- package/dist/objects/primitives/alarm-adapter.js +141 -0
- package/dist/objects/primitives/alarm-adapter.js.map +1 -0
- package/dist/objects/primitives/index.js +337 -0
- package/dist/objects/primitives/index.js.map +1 -0
- package/dist/objects/primitives/storage-adapter.js +182 -0
- package/dist/objects/primitives/storage-adapter.js.map +1 -0
- package/dist/objects/primitives/with-primitives.js +102 -0
- package/dist/objects/primitives/with-primitives.js.map +1 -0
- package/dist/objects/services/StoreManager.js +227 -0
- package/dist/objects/services/StoreManager.js.map +1 -0
- package/dist/objects/services/index.js +13 -0
- package/dist/objects/services/index.js.map +1 -0
- package/dist/objects/transport/auth-layer.js +1451 -0
- package/dist/objects/transport/auth-layer.js.map +1 -0
- package/dist/objects/transport/capnweb-target.js +355 -0
- package/dist/objects/transport/capnweb-target.js.map +1 -0
- package/dist/objects/transport/chain.js +441 -0
- package/dist/objects/transport/chain.js.map +1 -0
- package/dist/objects/transport/handler.js +58 -0
- package/dist/objects/transport/handler.js.map +1 -0
- package/dist/objects/transport/index.js +53 -0
- package/dist/objects/transport/index.js.map +1 -0
- package/dist/objects/transport/mcp-server.js +691 -0
- package/dist/objects/transport/mcp-server.js.map +1 -0
- package/dist/objects/transport/rest-autowire.js +1508 -0
- package/dist/objects/transport/rest-autowire.js.map +1 -0
- package/dist/objects/transport/rest-router.js +440 -0
- package/dist/objects/transport/rest-router.js.map +1 -0
- package/dist/objects/transport/rpc-server.js +1539 -0
- package/dist/objects/transport/rpc-server.js.map +1 -0
- package/dist/objects/transport/shared.js +576 -0
- package/dist/objects/transport/shared.js.map +1 -0
- package/dist/objects/transport/sync-engine.js +291 -0
- package/dist/objects/transport/sync-engine.js.map +1 -0
- package/dist/objects/transport/types.js +8 -0
- package/dist/objects/transport/types.js.map +1 -0
- package/dist/sandbox/index.js +258 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/snippets/artifacts-config.js +241 -0
- package/dist/snippets/artifacts-config.js.map +1 -0
- package/dist/snippets/artifacts-ingest.js +832 -0
- package/dist/snippets/artifacts-ingest.js.map +1 -0
- package/dist/snippets/artifacts-serve.js +1035 -0
- package/dist/snippets/artifacts-serve.js.map +1 -0
- package/dist/snippets/artifacts-types.js +161 -0
- package/dist/snippets/artifacts-types.js.map +1 -0
- package/dist/snippets/cache-probe.js +376 -0
- package/dist/snippets/cache-probe.js.map +1 -0
- package/dist/snippets/cache.js +10 -0
- package/dist/snippets/cache.js.map +1 -0
- package/dist/snippets/events.js +469 -0
- package/dist/snippets/events.js.map +1 -0
- package/dist/snippets/index.js +7 -0
- package/dist/snippets/index.js.map +1 -0
- package/dist/snippets/proxy.js +495 -0
- package/dist/snippets/proxy.js.map +1 -0
- package/dist/snippets/search.js +1759 -0
- package/dist/snippets/search.js.map +1 -0
- package/dist/streams/index.js +30 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/streams/observability.js +68 -0
- package/dist/streams/observability.js.map +1 -0
- package/dist/types/AI.js +92 -0
- package/dist/types/AI.js.map +1 -0
- package/dist/types/AIFunction.js +171 -0
- package/dist/types/AIFunction.js.map +1 -0
- package/dist/types/BrowseVerb.js +89 -0
- package/dist/types/BrowseVerb.js.map +1 -0
- package/dist/types/Browser.js +31 -0
- package/dist/types/Browser.js.map +1 -0
- package/dist/types/Chaos.js +15 -0
- package/dist/types/Chaos.js.map +1 -0
- package/dist/types/CloudflareBindings.js +109 -0
- package/dist/types/CloudflareBindings.js.map +1 -0
- package/dist/types/Collection.js +50 -0
- package/dist/types/Collection.js.map +1 -0
- package/dist/types/DO.js +2 -0
- package/dist/types/DO.js.map +1 -0
- package/dist/types/DOLocation.js +63 -0
- package/dist/types/DOLocation.js.map +1 -0
- package/dist/types/EventHandler.js +57 -0
- package/dist/types/EventHandler.js.map +1 -0
- package/dist/types/Experiment.js +33 -0
- package/dist/types/Experiment.js.map +1 -0
- package/dist/types/Flag.js +57 -0
- package/dist/types/Flag.js.map +1 -0
- package/dist/types/Lifecycle.js +13 -0
- package/dist/types/Lifecycle.js.map +1 -0
- package/dist/types/Location.js +169 -0
- package/dist/types/Location.js.map +1 -0
- package/dist/types/Noun.js +66 -0
- package/dist/types/Noun.js.map +1 -0
- package/dist/types/SessionEvent.js +194 -0
- package/dist/types/SessionEvent.js.map +1 -0
- package/dist/types/Thing.js +55 -0
- package/dist/types/Thing.js.map +1 -0
- package/dist/types/ThingDO.js +153 -0
- package/dist/types/ThingDO.js.map +1 -0
- package/dist/types/Things.js +2 -0
- package/dist/types/Things.js.map +1 -0
- package/dist/types/Verb.js +119 -0
- package/dist/types/Verb.js.map +1 -0
- package/dist/types/WorkflowContext.js +70 -0
- package/dist/types/WorkflowContext.js.map +1 -0
- package/dist/types/analytics-api.js +13 -0
- package/dist/types/analytics-api.js.map +1 -0
- package/dist/types/capabilities.js +135 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/drizzle.js +12 -0
- package/dist/types/drizzle.js.map +1 -0
- package/dist/types/event.js +201 -0
- package/dist/types/event.js.map +1 -0
- package/dist/types/fn.js +12 -0
- package/dist/types/fn.js.map +1 -0
- package/dist/types/iceberg.js +48 -0
- package/dist/types/iceberg.js.map +1 -0
- package/dist/types/ids.js +170 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/index.js +41 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/introspect.js +54 -0
- package/dist/types/introspect.js.map +1 -0
- package/dist/types/observability.js +124 -0
- package/dist/types/observability.js.map +1 -0
- package/dist/types/sync-protocol.js +175 -0
- package/dist/types/sync-protocol.js.map +1 -0
- package/dist/types/vector.js +13 -0
- package/dist/types/vector.js.map +1 -0
- package/dist/workflows/ScheduleManager.js +473 -0
- package/dist/workflows/ScheduleManager.js.map +1 -0
- package/dist/workflows/StepDOBridge.js +149 -0
- package/dist/workflows/StepDOBridge.js.map +1 -0
- package/dist/workflows/StepResultStorage.js +232 -0
- package/dist/workflows/StepResultStorage.js.map +1 -0
- package/dist/workflows/WaitForEventManager.js +461 -0
- package/dist/workflows/WaitForEventManager.js.map +1 -0
- package/dist/workflows/analyzer.js +332 -0
- package/dist/workflows/analyzer.js.map +1 -0
- package/dist/workflows/compat/activity-router.js +484 -0
- package/dist/workflows/compat/activity-router.js.map +1 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
- package/dist/workflows/compat/backends/index.js +14 -0
- package/dist/workflows/compat/backends/index.js.map +1 -0
- package/dist/workflows/compat/errors/index.js +375 -0
- package/dist/workflows/compat/errors/index.js.map +1 -0
- package/dist/workflows/compat/index.js +79 -0
- package/dist/workflows/compat/index.js.map +1 -0
- package/dist/workflows/compat/inngest/index.js +989 -0
- package/dist/workflows/compat/inngest/index.js.map +1 -0
- package/dist/workflows/compat/qstash/index.js +1263 -0
- package/dist/workflows/compat/qstash/index.js.map +1 -0
- package/dist/workflows/compat/temporal/activities.js +739 -0
- package/dist/workflows/compat/temporal/activities.js.map +1 -0
- package/dist/workflows/compat/temporal/child-workflows.js +154 -0
- package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
- package/dist/workflows/compat/temporal/client.js +381 -0
- package/dist/workflows/compat/temporal/client.js.map +1 -0
- package/dist/workflows/compat/temporal/context.js +309 -0
- package/dist/workflows/compat/temporal/context.js.map +1 -0
- package/dist/workflows/compat/temporal/determinism.js +216 -0
- package/dist/workflows/compat/temporal/determinism.js.map +1 -0
- package/dist/workflows/compat/temporal/errors.js +128 -0
- package/dist/workflows/compat/temporal/errors.js.map +1 -0
- package/dist/workflows/compat/temporal/index.js +2464 -0
- package/dist/workflows/compat/temporal/index.js.map +1 -0
- package/dist/workflows/compat/temporal/saga.js +504 -0
- package/dist/workflows/compat/temporal/saga.js.map +1 -0
- package/dist/workflows/compat/temporal/signals.js +364 -0
- package/dist/workflows/compat/temporal/signals.js.map +1 -0
- package/dist/workflows/compat/temporal/storage.js +271 -0
- package/dist/workflows/compat/temporal/storage.js.map +1 -0
- package/dist/workflows/compat/temporal/timers.js +347 -0
- package/dist/workflows/compat/temporal/timers.js.map +1 -0
- package/dist/workflows/compat/temporal/types.js +7 -0
- package/dist/workflows/compat/temporal/types.js.map +1 -0
- package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
- package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
- package/dist/workflows/compat/trigger/index.js +468 -0
- package/dist/workflows/compat/trigger/index.js.map +1 -0
- package/dist/workflows/compat/utils/index.js +69 -0
- package/dist/workflows/compat/utils/index.js.map +1 -0
- package/dist/workflows/context/correlation-capability.js +266 -0
- package/dist/workflows/context/correlation-capability.js.map +1 -0
- package/dist/workflows/context/correlation.js +484 -0
- package/dist/workflows/context/correlation.js.map +1 -0
- package/dist/workflows/context/experiment.js +289 -0
- package/dist/workflows/context/experiment.js.map +1 -0
- package/dist/workflows/context/flag.js +244 -0
- package/dist/workflows/context/flag.js.map +1 -0
- package/dist/workflows/context/foundation.js +648 -0
- package/dist/workflows/context/foundation.js.map +1 -0
- package/dist/workflows/context/human-base.js +106 -0
- package/dist/workflows/context/human-base.js.map +1 -0
- package/dist/workflows/context/human.js +368 -0
- package/dist/workflows/context/human.js.map +1 -0
- package/dist/workflows/context/measure.js +354 -0
- package/dist/workflows/context/measure.js.map +1 -0
- package/dist/workflows/context/rate-limit.js +358 -0
- package/dist/workflows/context/rate-limit.js.map +1 -0
- package/dist/workflows/context/user.js +117 -0
- package/dist/workflows/context/user.js.map +1 -0
- package/dist/workflows/context/vault.js +360 -0
- package/dist/workflows/context/vault.js.map +1 -0
- package/dist/workflows/data/entity-events/entity-events.js +489 -0
- package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
- package/dist/workflows/data/experiment/index.js +599 -0
- package/dist/workflows/data/experiment/index.js.map +1 -0
- package/dist/workflows/data/goal/context.js +558 -0
- package/dist/workflows/data/goal/context.js.map +1 -0
- package/dist/workflows/data/goal/index.js +32 -0
- package/dist/workflows/data/goal/index.js.map +1 -0
- package/dist/workflows/data/measure/index.js +840 -0
- package/dist/workflows/data/measure/index.js.map +1 -0
- package/dist/workflows/data/stream/index.js +1149 -0
- package/dist/workflows/data/stream/index.js.map +1 -0
- package/dist/workflows/data/track/context.js +883 -0
- package/dist/workflows/data/track/context.js.map +1 -0
- package/dist/workflows/data/track/index.js +15 -0
- package/dist/workflows/data/track/index.js.map +1 -0
- package/dist/workflows/data/view/context.js +864 -0
- package/dist/workflows/data/view/context.js.map +1 -0
- package/dist/workflows/domain.js +93 -0
- package/dist/workflows/domain.js.map +1 -0
- package/dist/workflows/flag.js +176 -0
- package/dist/workflows/flag.js.map +1 -0
- package/dist/workflows/flags.js +217 -0
- package/dist/workflows/flags.js.map +1 -0
- package/dist/workflows/hash.js +209 -0
- package/dist/workflows/hash.js.map +1 -0
- package/dist/workflows/index.js +50 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/on.js +378 -0
- package/dist/workflows/on.js.map +1 -0
- package/dist/workflows/pipeline-promise.js +481 -0
- package/dist/workflows/pipeline-promise.js.map +1 -0
- package/dist/workflows/pipeline-types.js +20 -0
- package/dist/workflows/pipeline-types.js.map +1 -0
- package/dist/workflows/proxy.js +76 -0
- package/dist/workflows/proxy.js.map +1 -0
- package/dist/workflows/runtime.js +310 -0
- package/dist/workflows/runtime.js.map +1 -0
- package/dist/workflows/schedule-builder.js +327 -0
- package/dist/workflows/schedule-builder.js.map +1 -0
- package/dist/workflows/visibility/index.js +146 -0
- package/dist/workflows/visibility/index.js.map +1 -0
- package/dist/workflows/visibility/query-parser.js +150 -0
- package/dist/workflows/visibility/query-parser.js.map +1 -0
- package/dist/workflows/visibility/store.js +223 -0
- package/dist/workflows/visibility/store.js.map +1 -0
- package/dist/workflows/visibility/types.js +30 -0
- package/dist/workflows/visibility/types.js.map +1 -0
- package/dist/workflows/workflow.js +53 -0
- package/dist/workflows/workflow.js.map +1 -0
- package/package.json +294 -46
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Experiment Context API for $.experiment()
|
|
3
|
+
*
|
|
4
|
+
* Provides a workflow context API for A/B testing experiments with support for:
|
|
5
|
+
* - $.experiment(id).allocate(userId) - Allocate user to variant
|
|
6
|
+
* - $.experiment(id).isEnabled() - Check if experiment is running
|
|
7
|
+
* - $.experiment(id).variant(name) - Get variant configuration
|
|
8
|
+
* - $.experiment(id).pause() / resume() / complete() - Lifecycle management
|
|
9
|
+
* - $.experiment(id).setTraffic(n) - Update traffic allocation
|
|
10
|
+
* - $.Experiment.create({...}) - Create new experiment
|
|
11
|
+
* - $.Experiment.list() - List all experiments
|
|
12
|
+
*
|
|
13
|
+
* @module workflows/context/experiment
|
|
14
|
+
*/
|
|
15
|
+
import { hashToInt } from '../hash';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// CONSTANTS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Maximum value for 32-bit hash (2^32 - 1)
|
|
21
|
+
*/
|
|
22
|
+
const MAX_HASH_VALUE = 0xffffffff;
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// CORE ALLOCATION LOGIC
|
|
25
|
+
// ============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* Check if user is in traffic allocation using deterministic hash
|
|
28
|
+
*/
|
|
29
|
+
function isInTraffic(experimentId, userId, traffic) {
|
|
30
|
+
if (traffic <= 0) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (traffic >= 1) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const hashInput = `${userId}:${experimentId}:traffic`;
|
|
37
|
+
const hashValue = hashToInt(hashInput);
|
|
38
|
+
const normalizedHash = hashValue / MAX_HASH_VALUE;
|
|
39
|
+
return normalizedHash < traffic;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Assign user to a variant based on weighted distribution using deterministic hash
|
|
43
|
+
*/
|
|
44
|
+
function assignVariant(experimentId, userId, variants) {
|
|
45
|
+
if (!variants || variants.length === 0) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
// Calculate total weight
|
|
49
|
+
const totalWeight = variants.reduce((sum, variant) => sum + variant.weight, 0);
|
|
50
|
+
if (totalWeight === 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
// Use a different hash input for variant assignment
|
|
54
|
+
const hashInput = `${userId}:${experimentId}:variant`;
|
|
55
|
+
const hashValue = hashToInt(hashInput);
|
|
56
|
+
const normalizedHash = hashValue / MAX_HASH_VALUE;
|
|
57
|
+
const targetValue = normalizedHash * totalWeight;
|
|
58
|
+
// Find the variant based on cumulative weights
|
|
59
|
+
let cumulativeWeight = 0;
|
|
60
|
+
for (const variant of variants) {
|
|
61
|
+
cumulativeWeight += variant.weight;
|
|
62
|
+
if (targetValue < cumulativeWeight) {
|
|
63
|
+
return variant;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Fallback to last variant (should not happen with proper weights)
|
|
67
|
+
return variants[variants.length - 1] ?? null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Allocate a user to an experiment
|
|
71
|
+
*
|
|
72
|
+
* Allocation order:
|
|
73
|
+
* 1. Check experiment exists (non-existent = not in experiment)
|
|
74
|
+
* 2. Check experiment status (not running = not in experiment)
|
|
75
|
+
* 3. Check traffic allocation using deterministic hash
|
|
76
|
+
* 4. Assign to variant using weighted distribution
|
|
77
|
+
*/
|
|
78
|
+
export function allocateUser(experiment, userId) {
|
|
79
|
+
// Experiment doesn't exist
|
|
80
|
+
if (!experiment) {
|
|
81
|
+
return {
|
|
82
|
+
inExperiment: false,
|
|
83
|
+
variant: null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// Check if experiment is running
|
|
87
|
+
if (experiment.status !== 'running') {
|
|
88
|
+
return {
|
|
89
|
+
inExperiment: false,
|
|
90
|
+
variant: null,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Check traffic allocation
|
|
94
|
+
if (!isInTraffic(experiment.id, userId, experiment.traffic)) {
|
|
95
|
+
return {
|
|
96
|
+
inExperiment: false,
|
|
97
|
+
variant: null,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Assign to variant
|
|
101
|
+
const variant = assignVariant(experiment.id, userId, experiment.variants);
|
|
102
|
+
if (variant) {
|
|
103
|
+
return {
|
|
104
|
+
inExperiment: true,
|
|
105
|
+
variant: variant.key,
|
|
106
|
+
payload: variant.payload,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// No variants assigned (shouldn't happen with valid experiment)
|
|
110
|
+
return {
|
|
111
|
+
inExperiment: true,
|
|
112
|
+
variant: null,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// CONTEXT FACTORY
|
|
117
|
+
// ============================================================================
|
|
118
|
+
/**
|
|
119
|
+
* Creates an experiment context ($) with experiment support
|
|
120
|
+
*
|
|
121
|
+
* This factory creates a context object with:
|
|
122
|
+
* - $.experiment(id) - Returns an ExperimentInstance for per-experiment operations
|
|
123
|
+
* - $.Experiment - Collection-level operations (create, list)
|
|
124
|
+
* - $._storage - Internal storage for test setup
|
|
125
|
+
*
|
|
126
|
+
* @param existingStorage - Optional existing storage to reuse (for testing consistency)
|
|
127
|
+
* @returns An ExperimentContext object with experiment API methods
|
|
128
|
+
*/
|
|
129
|
+
export function createExperimentContext(existingStorage) {
|
|
130
|
+
// Internal experiment storage
|
|
131
|
+
const storage = existingStorage ?? {
|
|
132
|
+
experiments: new Map(),
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Create an ExperimentInstance for a specific experiment ID
|
|
136
|
+
*/
|
|
137
|
+
function createExperimentInstance(id) {
|
|
138
|
+
return {
|
|
139
|
+
/**
|
|
140
|
+
* Allocate a user to this experiment
|
|
141
|
+
* Uses deterministic hashing for consistent per-user assignment
|
|
142
|
+
*/
|
|
143
|
+
async allocate(userId) {
|
|
144
|
+
const experiment = storage.experiments.get(id);
|
|
145
|
+
return allocateUser(experiment, userId);
|
|
146
|
+
},
|
|
147
|
+
/**
|
|
148
|
+
* Check if this experiment is enabled (running)
|
|
149
|
+
*/
|
|
150
|
+
async isEnabled() {
|
|
151
|
+
const experiment = storage.experiments.get(id);
|
|
152
|
+
if (!experiment) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
return experiment.status === 'running';
|
|
156
|
+
},
|
|
157
|
+
/**
|
|
158
|
+
* Get a specific variant by name
|
|
159
|
+
*/
|
|
160
|
+
async variant(name) {
|
|
161
|
+
const experiment = storage.experiments.get(id);
|
|
162
|
+
if (!experiment) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
return experiment.variants.find((v) => v.key === name);
|
|
166
|
+
},
|
|
167
|
+
/**
|
|
168
|
+
* Get the full experiment configuration
|
|
169
|
+
*/
|
|
170
|
+
async get() {
|
|
171
|
+
return storage.experiments.get(id);
|
|
172
|
+
},
|
|
173
|
+
/**
|
|
174
|
+
* Pause the experiment
|
|
175
|
+
*/
|
|
176
|
+
async pause() {
|
|
177
|
+
const experiment = storage.experiments.get(id);
|
|
178
|
+
if (!experiment) {
|
|
179
|
+
throw new Error(`Experiment '${id}' does not exist`);
|
|
180
|
+
}
|
|
181
|
+
experiment.status = 'paused';
|
|
182
|
+
experiment.updatedAt = new Date();
|
|
183
|
+
storage.experiments.set(id, experiment);
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Resume a paused experiment
|
|
187
|
+
*/
|
|
188
|
+
async resume() {
|
|
189
|
+
const experiment = storage.experiments.get(id);
|
|
190
|
+
if (!experiment) {
|
|
191
|
+
throw new Error(`Experiment '${id}' does not exist`);
|
|
192
|
+
}
|
|
193
|
+
experiment.status = 'running';
|
|
194
|
+
experiment.updatedAt = new Date();
|
|
195
|
+
storage.experiments.set(id, experiment);
|
|
196
|
+
},
|
|
197
|
+
/**
|
|
198
|
+
* Complete the experiment
|
|
199
|
+
*/
|
|
200
|
+
async complete() {
|
|
201
|
+
const experiment = storage.experiments.get(id);
|
|
202
|
+
if (!experiment) {
|
|
203
|
+
throw new Error(`Experiment '${id}' does not exist`);
|
|
204
|
+
}
|
|
205
|
+
experiment.status = 'completed';
|
|
206
|
+
experiment.updatedAt = new Date();
|
|
207
|
+
storage.experiments.set(id, experiment);
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* Update traffic allocation
|
|
211
|
+
* @param traffic - Value between 0 and 1
|
|
212
|
+
*/
|
|
213
|
+
async setTraffic(traffic) {
|
|
214
|
+
if (traffic < 0 || traffic > 1) {
|
|
215
|
+
throw new Error(`Traffic must be between 0 and 1, got ${traffic}`);
|
|
216
|
+
}
|
|
217
|
+
const experiment = storage.experiments.get(id);
|
|
218
|
+
if (!experiment) {
|
|
219
|
+
throw new Error(`Experiment '${id}' does not exist`);
|
|
220
|
+
}
|
|
221
|
+
experiment.traffic = traffic;
|
|
222
|
+
experiment.updatedAt = new Date();
|
|
223
|
+
storage.experiments.set(id, experiment);
|
|
224
|
+
},
|
|
225
|
+
/**
|
|
226
|
+
* Delete the experiment
|
|
227
|
+
*/
|
|
228
|
+
async delete() {
|
|
229
|
+
storage.experiments.delete(id);
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Experiment collection API
|
|
235
|
+
*/
|
|
236
|
+
const experimentCollection = {
|
|
237
|
+
/**
|
|
238
|
+
* Create a new experiment
|
|
239
|
+
*/
|
|
240
|
+
async create(options) {
|
|
241
|
+
// Validate experiment doesn't already exist
|
|
242
|
+
if (storage.experiments.has(options.id)) {
|
|
243
|
+
throw new Error(`Experiment '${options.id}' already exists`);
|
|
244
|
+
}
|
|
245
|
+
// Validate at least 2 variants
|
|
246
|
+
if (!options.variants || options.variants.length < 2) {
|
|
247
|
+
throw new Error('Experiment must have at least 2 variants');
|
|
248
|
+
}
|
|
249
|
+
// Validate all weights are positive
|
|
250
|
+
for (const variant of options.variants) {
|
|
251
|
+
if (variant.weight < 0) {
|
|
252
|
+
throw new Error(`Variant weight must be non-negative, got ${variant.weight}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Validate traffic
|
|
256
|
+
const traffic = options.traffic ?? 1.0;
|
|
257
|
+
if (traffic < 0 || traffic > 1) {
|
|
258
|
+
throw new Error(`Traffic must be between 0 and 1, got ${traffic}`);
|
|
259
|
+
}
|
|
260
|
+
const now = new Date();
|
|
261
|
+
const experiment = {
|
|
262
|
+
id: options.id,
|
|
263
|
+
traffic,
|
|
264
|
+
status: options.status ?? 'running',
|
|
265
|
+
variants: options.variants.map((v) => ({
|
|
266
|
+
key: v.key,
|
|
267
|
+
weight: v.weight,
|
|
268
|
+
payload: v.payload,
|
|
269
|
+
})),
|
|
270
|
+
createdAt: now,
|
|
271
|
+
updatedAt: now,
|
|
272
|
+
};
|
|
273
|
+
storage.experiments.set(options.id, experiment);
|
|
274
|
+
return experiment;
|
|
275
|
+
},
|
|
276
|
+
/**
|
|
277
|
+
* List all experiments
|
|
278
|
+
*/
|
|
279
|
+
async list() {
|
|
280
|
+
return Array.from(storage.experiments.values());
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
return {
|
|
284
|
+
experiment: createExperimentInstance,
|
|
285
|
+
Experiment: experimentCollection,
|
|
286
|
+
_storage: storage,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=experiment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiment.js","sourceRoot":"","sources":["../../../workflows/context/experiment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AA0FnC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;GAEG;AACH,MAAM,cAAc,GAAG,UAAU,CAAA;AAEjC,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;GAEG;AACH,SAAS,WAAW,CAAC,YAAoB,EAAE,MAAc,EAAE,OAAe;IACxE,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,YAAY,UAAU,CAAA;IACrD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,cAAc,GAAG,SAAS,GAAG,cAAc,CAAA;IAEjD,OAAO,cAAc,GAAG,OAAO,CAAA;AACjC,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CACpB,YAAoB,EACpB,MAAc,EACd,QAAmB;IAEnB,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yBAAyB;IACzB,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9E,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,YAAY,UAAU,CAAA;IACrD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,cAAc,GAAG,SAAS,GAAG,cAAc,CAAA;IACjD,MAAM,WAAW,GAAG,cAAc,GAAG,WAAW,CAAA;IAEhD,+CAA+C;IAC/C,IAAI,gBAAgB,GAAG,CAAC,CAAA;IACxB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAA;QAClC,IAAI,WAAW,GAAG,gBAAgB,EAAE,CAAC;YACnC,OAAO,OAAO,CAAA;QAChB,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAA;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAkC,EAClC,MAAc;IAEd,2BAA2B;IAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IAED,iCAAiC;IACjC,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IAED,oBAAoB;IACpB,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IACzE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,YAAY,EAAE,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,GAAG;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAA;IACH,CAAC;IAED,gEAAgE;IAChE,OAAO;QACL,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,IAAI;KACd,CAAA;AACH,CAAC;AAED,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAmC;IACzE,8BAA8B;IAC9B,MAAM,OAAO,GAAsB,eAAe,IAAI;QACpD,WAAW,EAAE,IAAI,GAAG,EAAsB;KAC3C,CAAA;IAED;;OAEG;IACH,SAAS,wBAAwB,CAAC,EAAU;QAC1C,OAAO;YACL;;;eAGG;YACH,KAAK,CAAC,QAAQ,CAAC,MAAc;gBAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,OAAO,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;YACzC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,SAAS;gBACb,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,OAAO,KAAK,CAAA;gBACd,CAAC;gBACD,OAAO,UAAU,CAAC,MAAM,KAAK,SAAS,CAAA;YACxC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,OAAO,CAAC,IAAY;gBACxB,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,OAAO,SAAS,CAAA;gBAClB,CAAC;gBACD,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAA;YACxD,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,GAAG;gBACP,OAAO,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACpC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,KAAK;gBACT,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAA;gBACtD,CAAC;gBAED,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAA;gBAC5B,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;gBACjC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;YACzC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,MAAM;gBACV,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAA;gBACtD,CAAC;gBAED,UAAU,CAAC,MAAM,GAAG,SAAS,CAAA;gBAC7B,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;gBACjC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;YACzC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,QAAQ;gBACZ,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAA;gBACtD,CAAC;gBAED,UAAU,CAAC,MAAM,GAAG,WAAW,CAAA;gBAC/B,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;gBACjC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;YACzC,CAAC;YAED;;;eAGG;YACH,KAAK,CAAC,UAAU,CAAC,OAAe;gBAC9B,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC/B,MAAM,IAAI,KAAK,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAA;gBACpE,CAAC;gBAED,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAA;gBACtD,CAAC;gBAED,UAAU,CAAC,OAAO,GAAG,OAAO,CAAA;gBAC5B,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;gBACjC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;YACzC,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,MAAM;gBACV,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAChC,CAAC;SACF,CAAA;IACH,CAAC;IAED;;OAEG;IACH,MAAM,oBAAoB,GAAyB;QACjD;;WAEG;QACH,KAAK,CAAC,MAAM,CAAC,OAAgC;YAC3C,4CAA4C;YAC5C,IAAI,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,eAAe,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAA;YAC9D,CAAC;YAED,+BAA+B;YAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;YAC7D,CAAC;YAED,oCAAoC;YACpC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACvC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;gBAC/E,CAAC;YACH,CAAC;YAED,mBAAmB;YACnB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAA;YACtC,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAA;YACpE,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;YACtB,MAAM,UAAU,GAAe;gBAC7B,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,OAAO;gBACP,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;gBACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACrC,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,OAAO,EAAE,CAAC,CAAC,OAAO;iBACnB,CAAC,CAAC;gBACH,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE,GAAG;aACf,CAAA;YAED,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;YAC/C,OAAO,UAAU,CAAA;QACnB,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,IAAI;YACR,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAA;QACjD,CAAC;KACF,CAAA;IAED,OAAO;QACL,UAAU,EAAE,wBAAwB;QACpC,UAAU,EAAE,oBAAoB;QAChC,QAAQ,EAAE,OAAO;KAClB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Flag Context API for $.flag() and $.flags
|
|
3
|
+
*
|
|
4
|
+
* Provides a workflow context API for feature flag evaluation with support for:
|
|
5
|
+
* - $.flag(id).isEnabled(userId) - Check if flag is enabled for user
|
|
6
|
+
* - $.flag(id).get(userId) - Get full evaluation result with variant/payload
|
|
7
|
+
* - $.flag(id).setTraffic(n) - Update traffic allocation
|
|
8
|
+
* - $.flag(id).enable() - Enable flag for all users
|
|
9
|
+
* - $.flag(id).disable() - Disable flag
|
|
10
|
+
* - $.flags.fetch() - Fetch all flags from storage
|
|
11
|
+
* - $.flags.evaluate(id, userId, flags) - Local evaluation without DB
|
|
12
|
+
*
|
|
13
|
+
* @module workflows/context/flag
|
|
14
|
+
*/
|
|
15
|
+
import { hashToInt } from '../hash';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// CONSTANTS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Maximum value for 32-bit hash (2^32 - 1)
|
|
21
|
+
*/
|
|
22
|
+
const MAX_HASH_VALUE = 0xffffffff;
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// CORE EVALUATION LOGIC
|
|
25
|
+
// ============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* Check if user is in traffic allocation using deterministic hash
|
|
28
|
+
*/
|
|
29
|
+
function isInTraffic(flagId, userId, traffic) {
|
|
30
|
+
if (traffic <= 0) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (traffic >= 1) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const hashInput = `${userId}:${flagId}`;
|
|
37
|
+
const hashValue = hashToInt(hashInput);
|
|
38
|
+
const normalizedHash = hashValue / MAX_HASH_VALUE;
|
|
39
|
+
return normalizedHash < traffic;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Assign user to a branch based on weighted distribution using deterministic hash
|
|
43
|
+
*/
|
|
44
|
+
function assignBranch(flagId, userId, branches) {
|
|
45
|
+
if (!branches || branches.length === 0) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
// Calculate total weight
|
|
49
|
+
const totalWeight = branches.reduce((sum, branch) => sum + branch.weight, 0);
|
|
50
|
+
if (totalWeight === 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
// Use a different hash input for branch assignment to get independent randomization
|
|
54
|
+
const hashInput = `${userId}:${flagId}:branch`;
|
|
55
|
+
const hashValue = hashToInt(hashInput);
|
|
56
|
+
const normalizedHash = hashValue / MAX_HASH_VALUE;
|
|
57
|
+
const targetValue = normalizedHash * totalWeight;
|
|
58
|
+
// Find the branch based on cumulative weights
|
|
59
|
+
let cumulativeWeight = 0;
|
|
60
|
+
for (const branch of branches) {
|
|
61
|
+
cumulativeWeight += branch.weight;
|
|
62
|
+
if (targetValue < cumulativeWeight) {
|
|
63
|
+
return branch;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Fallback to last branch (should not happen with proper weights)
|
|
67
|
+
return branches[branches.length - 1] ?? null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Evaluate a flag for a given user
|
|
71
|
+
*
|
|
72
|
+
* Evaluation order:
|
|
73
|
+
* 1. Check flag exists (non-existent = disabled)
|
|
74
|
+
* 2. Check flag status (disabled = disabled)
|
|
75
|
+
* 3. Check traffic allocation using deterministic hash
|
|
76
|
+
* 4. Assign to branch using weighted distribution
|
|
77
|
+
*
|
|
78
|
+
* @param flag - The flag configuration (or undefined if not found)
|
|
79
|
+
* @param userId - The user ID for deterministic assignment
|
|
80
|
+
* @returns The evaluation result with enabled status, variant, and optional payload
|
|
81
|
+
*/
|
|
82
|
+
export function evaluateFlag(flag, userId) {
|
|
83
|
+
// Flag doesn't exist - return disabled
|
|
84
|
+
if (!flag) {
|
|
85
|
+
return {
|
|
86
|
+
enabled: false,
|
|
87
|
+
variant: null,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// Check if flag status is disabled
|
|
91
|
+
if (flag.status === 'disabled' || flag.status === 'archived') {
|
|
92
|
+
return {
|
|
93
|
+
enabled: false,
|
|
94
|
+
variant: null,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Check traffic allocation
|
|
98
|
+
if (!isInTraffic(flag.id, userId, flag.traffic)) {
|
|
99
|
+
return {
|
|
100
|
+
enabled: false,
|
|
101
|
+
variant: null,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Assign to branch
|
|
105
|
+
const branch = assignBranch(flag.id, userId, flag.branches);
|
|
106
|
+
if (branch) {
|
|
107
|
+
return {
|
|
108
|
+
enabled: true,
|
|
109
|
+
variant: branch.key,
|
|
110
|
+
payload: branch.payload,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// No branches - just enabled
|
|
114
|
+
return {
|
|
115
|
+
enabled: true,
|
|
116
|
+
variant: null,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// CONTEXT FACTORY
|
|
121
|
+
// ============================================================================
|
|
122
|
+
/**
|
|
123
|
+
* Creates a mock workflow context ($) with flag support for testing
|
|
124
|
+
*
|
|
125
|
+
* This factory creates a context object with:
|
|
126
|
+
* - $.flag(id) - Returns a FlagContextInstance for per-flag operations
|
|
127
|
+
* - $.flags - Collection-level operations (fetch, evaluate)
|
|
128
|
+
* - $._storage - Internal storage for test setup
|
|
129
|
+
*
|
|
130
|
+
* @returns A FlagContext object with flag API methods
|
|
131
|
+
*/
|
|
132
|
+
export function createMockContext() {
|
|
133
|
+
// Internal flag storage
|
|
134
|
+
const storage = {
|
|
135
|
+
flags: new Map(),
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Create a FlagContextInstance for a specific flag ID
|
|
139
|
+
*/
|
|
140
|
+
function createFlagInstance(id) {
|
|
141
|
+
return {
|
|
142
|
+
/**
|
|
143
|
+
* Check if a user is enabled for this flag
|
|
144
|
+
* Uses deterministic hashing for consistent per-user assignment
|
|
145
|
+
*/
|
|
146
|
+
async isEnabled(userId) {
|
|
147
|
+
const flag = storage.flags.get(id);
|
|
148
|
+
const result = evaluateFlag(flag, userId);
|
|
149
|
+
return result.enabled;
|
|
150
|
+
},
|
|
151
|
+
/**
|
|
152
|
+
* Get full evaluation result including variant and payload
|
|
153
|
+
*/
|
|
154
|
+
async get(userId) {
|
|
155
|
+
const flag = storage.flags.get(id);
|
|
156
|
+
return evaluateFlag(flag, userId);
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* Update traffic allocation for this flag
|
|
160
|
+
* @param traffic - Value between 0 and 1
|
|
161
|
+
*/
|
|
162
|
+
async setTraffic(traffic) {
|
|
163
|
+
// Validate traffic range
|
|
164
|
+
if (traffic < 0 || traffic > 1) {
|
|
165
|
+
throw new Error(`Traffic must be between 0 and 1, got ${traffic}`);
|
|
166
|
+
}
|
|
167
|
+
const flag = storage.flags.get(id);
|
|
168
|
+
if (!flag) {
|
|
169
|
+
throw new Error(`Flag '${id}' does not exist`);
|
|
170
|
+
}
|
|
171
|
+
flag.traffic = traffic;
|
|
172
|
+
flag.updatedAt = new Date();
|
|
173
|
+
storage.flags.set(id, flag);
|
|
174
|
+
},
|
|
175
|
+
/**
|
|
176
|
+
* Enable the flag for all users
|
|
177
|
+
* Sets traffic to 1.0 and status to active
|
|
178
|
+
*/
|
|
179
|
+
async enable() {
|
|
180
|
+
const flag = storage.flags.get(id);
|
|
181
|
+
if (!flag) {
|
|
182
|
+
throw new Error(`Flag '${id}' does not exist`);
|
|
183
|
+
}
|
|
184
|
+
flag.traffic = 1.0;
|
|
185
|
+
flag.status = 'active';
|
|
186
|
+
flag.updatedAt = new Date();
|
|
187
|
+
storage.flags.set(id, flag);
|
|
188
|
+
},
|
|
189
|
+
/**
|
|
190
|
+
* Disable the flag for all users
|
|
191
|
+
* Sets status to disabled but preserves traffic value
|
|
192
|
+
*/
|
|
193
|
+
async disable() {
|
|
194
|
+
const flag = storage.flags.get(id);
|
|
195
|
+
if (!flag) {
|
|
196
|
+
throw new Error(`Flag '${id}' does not exist`);
|
|
197
|
+
}
|
|
198
|
+
flag.status = 'disabled';
|
|
199
|
+
flag.updatedAt = new Date();
|
|
200
|
+
storage.flags.set(id, flag);
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Flags collection API
|
|
206
|
+
*/
|
|
207
|
+
const flagsCollection = {
|
|
208
|
+
/**
|
|
209
|
+
* Fetch all flags from storage
|
|
210
|
+
* Returns a deep copy to prevent mutations
|
|
211
|
+
*/
|
|
212
|
+
async fetch() {
|
|
213
|
+
const result = {};
|
|
214
|
+
for (const [key, flag] of storage.flags.entries()) {
|
|
215
|
+
// Create a deep copy to prevent mutations affecting storage
|
|
216
|
+
result[key] = {
|
|
217
|
+
...flag,
|
|
218
|
+
branches: flag.branches.map((b) => ({ ...b })),
|
|
219
|
+
createdAt: new Date(flag.createdAt.getTime()),
|
|
220
|
+
updatedAt: new Date(flag.updatedAt.getTime()),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
},
|
|
225
|
+
/**
|
|
226
|
+
* Evaluate a flag locally against provided flags object
|
|
227
|
+
* This is synchronous and doesn't hit storage
|
|
228
|
+
*
|
|
229
|
+
* @param flagId - The flag ID to evaluate
|
|
230
|
+
* @param userId - The user ID for deterministic assignment
|
|
231
|
+
* @param flags - The flags object to evaluate against
|
|
232
|
+
*/
|
|
233
|
+
evaluate(flagId, userId, flags) {
|
|
234
|
+
const flag = flags[flagId];
|
|
235
|
+
return evaluateFlag(flag, userId);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
flag: createFlagInstance,
|
|
240
|
+
flags: flagsCollection,
|
|
241
|
+
_storage: storage,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=flag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sourceRoot":"","sources":["../../../workflows/context/flag.ts"],"names":[],"mappings":"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"}
|