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,864 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View Context Implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides materialized views API ($.view) with:
|
|
5
|
+
* - $.view.define('name', { from, groupBy, compute }) - Define materialized views
|
|
6
|
+
* - $.view.X.get() - Query full view
|
|
7
|
+
* - $.view.X.get(key) - Query single key
|
|
8
|
+
* - $.view.X.where().limit().get() - Filtered queries
|
|
9
|
+
* - $.view.X.subscribe() - Real-time updates
|
|
10
|
+
* - $.view.X.refresh() - Manual refresh
|
|
11
|
+
*
|
|
12
|
+
* @module workflows/data/view/context
|
|
13
|
+
*/
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Implementation
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Create a view context for testing
|
|
19
|
+
*/
|
|
20
|
+
export function createViewContext() {
|
|
21
|
+
// Storage
|
|
22
|
+
const storage = {
|
|
23
|
+
views: new Map(),
|
|
24
|
+
viewData: new Map(),
|
|
25
|
+
events: new Map(),
|
|
26
|
+
retractedEvents: new Map(),
|
|
27
|
+
checkpoints: new Map(),
|
|
28
|
+
disabledSources: new Set(),
|
|
29
|
+
};
|
|
30
|
+
// Subscriptions
|
|
31
|
+
const subscriptions = new Map();
|
|
32
|
+
// Event handlers
|
|
33
|
+
const eventHandlers = new Map();
|
|
34
|
+
// Scheduled tasks
|
|
35
|
+
const scheduledTasks = [];
|
|
36
|
+
// Internal time tracking - can be advanced for testing
|
|
37
|
+
let currentTime = Date.now();
|
|
38
|
+
// Event sequence numbers for incremental refresh tracking
|
|
39
|
+
let globalEventSequence = 0;
|
|
40
|
+
const eventSequenceNumbers = new Map();
|
|
41
|
+
// Cache for view instances to enable spying
|
|
42
|
+
const viewInstanceCache = new Map();
|
|
43
|
+
// Helper to get group key
|
|
44
|
+
const getGroupKey = (event, groupBy) => {
|
|
45
|
+
if (Array.isArray(groupBy)) {
|
|
46
|
+
return groupBy.map(k => String(event[k] ?? 'undefined')).join(':');
|
|
47
|
+
}
|
|
48
|
+
return String(event[groupBy] ?? 'undefined');
|
|
49
|
+
};
|
|
50
|
+
// Helper to parse group key back to object
|
|
51
|
+
const parseGroupKey = (key, groupBy) => {
|
|
52
|
+
if (Array.isArray(groupBy)) {
|
|
53
|
+
const parts = key.split(':');
|
|
54
|
+
const result = {};
|
|
55
|
+
groupBy.forEach((k, i) => {
|
|
56
|
+
result[k] = parts[i] === 'undefined' ? undefined : parts[i];
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
return { [groupBy]: key === 'undefined' ? undefined : key };
|
|
61
|
+
};
|
|
62
|
+
// Helper to compute aggregates
|
|
63
|
+
const computeAggregates = (events, compute, groupBy) => {
|
|
64
|
+
const groups = new Map();
|
|
65
|
+
// Group events
|
|
66
|
+
for (const event of events) {
|
|
67
|
+
const key = getGroupKey(event, groupBy);
|
|
68
|
+
if (!groups.has(key)) {
|
|
69
|
+
groups.set(key, []);
|
|
70
|
+
}
|
|
71
|
+
groups.get(key).push(event);
|
|
72
|
+
}
|
|
73
|
+
// Compute aggregates for each group
|
|
74
|
+
const results = new Map();
|
|
75
|
+
for (const [key, groupEvents] of groups) {
|
|
76
|
+
const row = { ...parseGroupKey(key, groupBy) };
|
|
77
|
+
for (const [fieldName, agg] of Object.entries(compute)) {
|
|
78
|
+
row[fieldName] = computeAggregate(groupEvents, agg);
|
|
79
|
+
}
|
|
80
|
+
results.set(key, row);
|
|
81
|
+
}
|
|
82
|
+
return results;
|
|
83
|
+
};
|
|
84
|
+
// Helper to compute a single aggregate
|
|
85
|
+
const computeAggregate = (events, agg) => {
|
|
86
|
+
switch (agg.type) {
|
|
87
|
+
case 'count':
|
|
88
|
+
return events.length;
|
|
89
|
+
case 'sum': {
|
|
90
|
+
let sum = 0;
|
|
91
|
+
for (const e of events) {
|
|
92
|
+
const val = e[agg.field];
|
|
93
|
+
if (val !== null && val !== undefined) {
|
|
94
|
+
const num = typeof val === 'string' ? parseFloat(val) : val;
|
|
95
|
+
if (typeof num === 'number' && !isNaN(num)) {
|
|
96
|
+
sum += num;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return sum;
|
|
101
|
+
}
|
|
102
|
+
case 'avg': {
|
|
103
|
+
let sum = 0;
|
|
104
|
+
let count = 0;
|
|
105
|
+
for (const e of events) {
|
|
106
|
+
const val = e[agg.field];
|
|
107
|
+
if (val !== null && val !== undefined) {
|
|
108
|
+
const num = typeof val === 'string' ? parseFloat(val) : val;
|
|
109
|
+
if (typeof num === 'number' && !isNaN(num)) {
|
|
110
|
+
sum += num;
|
|
111
|
+
count++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return count > 0 ? sum / count : 0;
|
|
116
|
+
}
|
|
117
|
+
case 'min': {
|
|
118
|
+
let min = Infinity;
|
|
119
|
+
for (const e of events) {
|
|
120
|
+
const val = e[agg.field];
|
|
121
|
+
if (val !== null && val !== undefined && typeof val === 'number' && val < min) {
|
|
122
|
+
min = val;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return min === Infinity ? 0 : min;
|
|
126
|
+
}
|
|
127
|
+
case 'max': {
|
|
128
|
+
let max = -Infinity;
|
|
129
|
+
for (const e of events) {
|
|
130
|
+
const val = e[agg.field];
|
|
131
|
+
if (val !== null && val !== undefined && typeof val === 'number' && val > max) {
|
|
132
|
+
max = val;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return max === -Infinity ? 0 : max;
|
|
136
|
+
}
|
|
137
|
+
case 'first': {
|
|
138
|
+
for (const e of events) {
|
|
139
|
+
const val = e[agg.field];
|
|
140
|
+
if (val !== undefined) {
|
|
141
|
+
return val;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
case 'last': {
|
|
147
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
148
|
+
const val = events[i][agg.field];
|
|
149
|
+
if (val !== undefined) {
|
|
150
|
+
return val;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
case 'countDistinct': {
|
|
156
|
+
const seen = new Set();
|
|
157
|
+
for (const e of events) {
|
|
158
|
+
const val = e[agg.field];
|
|
159
|
+
if (val !== undefined) {
|
|
160
|
+
seen.add(val);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return seen.size;
|
|
164
|
+
}
|
|
165
|
+
default:
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
// Helper to notify subscribers
|
|
170
|
+
const notifySubscribers = (viewName, changes) => {
|
|
171
|
+
const subs = subscriptions.get(viewName);
|
|
172
|
+
if (!subs)
|
|
173
|
+
return;
|
|
174
|
+
for (const sub of subs) {
|
|
175
|
+
// Check filter
|
|
176
|
+
if (sub.options?.where) {
|
|
177
|
+
const row = changes.after ?? changes.row;
|
|
178
|
+
if (row && !matchesFilter(row, sub.options.where)) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (typeof sub.callback === 'function') {
|
|
183
|
+
const payload = changes.after ?? changes.row ?? changes;
|
|
184
|
+
sub.callback(payload);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
if (changes.type === 'insert' && sub.callback.onInsert) {
|
|
188
|
+
sub.callback.onInsert(changes.row);
|
|
189
|
+
}
|
|
190
|
+
else if (changes.type === 'update' && sub.callback.onUpdate) {
|
|
191
|
+
sub.callback.onUpdate(changes.before, changes.after);
|
|
192
|
+
}
|
|
193
|
+
else if (changes.type === 'delete' && sub.callback.onDelete) {
|
|
194
|
+
sub.callback.onDelete(changes.row);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
// Helper to match filter conditions
|
|
200
|
+
const matchesFilter = (row, condition) => {
|
|
201
|
+
for (const [key, value] of Object.entries(condition)) {
|
|
202
|
+
const rowValue = row[key];
|
|
203
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
204
|
+
const ops = value;
|
|
205
|
+
for (const [op, opValue] of Object.entries(ops)) {
|
|
206
|
+
switch (op) {
|
|
207
|
+
case 'gt':
|
|
208
|
+
if (!(typeof rowValue === 'number' && rowValue > opValue))
|
|
209
|
+
return false;
|
|
210
|
+
break;
|
|
211
|
+
case 'gte':
|
|
212
|
+
if (!(typeof rowValue === 'number' && rowValue >= opValue))
|
|
213
|
+
return false;
|
|
214
|
+
break;
|
|
215
|
+
case 'lt':
|
|
216
|
+
if (!(typeof rowValue === 'number' && rowValue < opValue))
|
|
217
|
+
return false;
|
|
218
|
+
break;
|
|
219
|
+
case 'lte':
|
|
220
|
+
if (!(typeof rowValue === 'number' && rowValue <= opValue))
|
|
221
|
+
return false;
|
|
222
|
+
break;
|
|
223
|
+
case 'ne':
|
|
224
|
+
if (rowValue === opValue)
|
|
225
|
+
return false;
|
|
226
|
+
break;
|
|
227
|
+
case 'in':
|
|
228
|
+
if (!Array.isArray(opValue) || !opValue.includes(rowValue))
|
|
229
|
+
return false;
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
if (rowValue !== value)
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return true;
|
|
240
|
+
};
|
|
241
|
+
// Helper to update view data
|
|
242
|
+
const updateViewData = async (viewName, viewDef, newEvents) => {
|
|
243
|
+
if (!storage.viewData.has(viewName)) {
|
|
244
|
+
storage.viewData.set(viewName, new Map());
|
|
245
|
+
}
|
|
246
|
+
const data = storage.viewData.get(viewName);
|
|
247
|
+
for (const event of newEvents) {
|
|
248
|
+
// Check where filter
|
|
249
|
+
if (viewDef.where && !viewDef.where(event)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const key = getGroupKey(event, viewDef.groupBy);
|
|
253
|
+
const existing = data.get(key);
|
|
254
|
+
if (existing) {
|
|
255
|
+
// Update existing row
|
|
256
|
+
const before = { ...existing };
|
|
257
|
+
// Re-compute aggregates for this group
|
|
258
|
+
const sourceKey = `${viewDef.from._type}.${viewDef.from._event}`;
|
|
259
|
+
const allEvents = storage.events.get(sourceKey) ?? [];
|
|
260
|
+
const groupEvents = allEvents.filter(e => {
|
|
261
|
+
if (viewDef.where && !viewDef.where(e))
|
|
262
|
+
return false;
|
|
263
|
+
return getGroupKey(e, viewDef.groupBy) === key;
|
|
264
|
+
});
|
|
265
|
+
const newRow = { ...parseGroupKey(key, viewDef.groupBy) };
|
|
266
|
+
for (const [fieldName, agg] of Object.entries(viewDef.compute)) {
|
|
267
|
+
newRow[fieldName] = computeAggregate(groupEvents, agg);
|
|
268
|
+
}
|
|
269
|
+
data.set(key, newRow);
|
|
270
|
+
notifySubscribers(viewName, { type: 'update', before, after: newRow });
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// Insert new row
|
|
274
|
+
const sourceKey = `${viewDef.from._type}.${viewDef.from._event}`;
|
|
275
|
+
const allEvents = storage.events.get(sourceKey) ?? [];
|
|
276
|
+
const groupEvents = allEvents.filter(e => {
|
|
277
|
+
if (viewDef.where && !viewDef.where(e))
|
|
278
|
+
return false;
|
|
279
|
+
return getGroupKey(e, viewDef.groupBy) === key;
|
|
280
|
+
});
|
|
281
|
+
const newRow = { ...parseGroupKey(key, viewDef.groupBy) };
|
|
282
|
+
for (const [fieldName, agg] of Object.entries(viewDef.compute)) {
|
|
283
|
+
newRow[fieldName] = computeAggregate(groupEvents, agg);
|
|
284
|
+
}
|
|
285
|
+
data.set(key, newRow);
|
|
286
|
+
notifySubscribers(viewName, { type: 'insert', row: newRow });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Update row count
|
|
290
|
+
viewDef.rowCount = data.size;
|
|
291
|
+
};
|
|
292
|
+
// Helper to refresh view
|
|
293
|
+
const refreshView = async (viewName, options) => {
|
|
294
|
+
const viewDef = storage.views.get(viewName);
|
|
295
|
+
if (!viewDef) {
|
|
296
|
+
throw new Error(`View '${viewName}' not found`);
|
|
297
|
+
}
|
|
298
|
+
const start = Date.now();
|
|
299
|
+
// Get source key
|
|
300
|
+
const sourceKey = viewDef.from._type === 'track'
|
|
301
|
+
? `track.${viewDef.from._event}`
|
|
302
|
+
: `stream.${viewDef.from._event}`;
|
|
303
|
+
// Check if source is disabled
|
|
304
|
+
if (storage.disabledSources.has(sourceKey)) {
|
|
305
|
+
throw new Error(`Source '${sourceKey}' is unavailable`);
|
|
306
|
+
}
|
|
307
|
+
// Get events
|
|
308
|
+
const allEvents = storage.events.get(sourceKey) ?? [];
|
|
309
|
+
const sequences = eventSequenceNumbers.get(sourceKey) ?? [];
|
|
310
|
+
let events = [];
|
|
311
|
+
// Filter by time if incremental
|
|
312
|
+
if (options?.incremental) {
|
|
313
|
+
if (options.since !== undefined) {
|
|
314
|
+
// User provided explicit since timestamp - filter by event's timestamp field
|
|
315
|
+
for (const event of allEvents) {
|
|
316
|
+
const eventTs = event.timestamp ?? 0;
|
|
317
|
+
if (eventTs >= options.since) {
|
|
318
|
+
events.push(event);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
// No explicit since - use checkpoint (last processed sequence number)
|
|
324
|
+
const checkpoint = storage.checkpoints.get(viewName) ?? 0;
|
|
325
|
+
for (let i = 0; i < allEvents.length; i++) {
|
|
326
|
+
const seq = sequences[i] ?? 0;
|
|
327
|
+
if (seq > checkpoint) {
|
|
328
|
+
events.push(allEvents[i]);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
events = [...allEvents];
|
|
335
|
+
}
|
|
336
|
+
// Apply where filter
|
|
337
|
+
if (viewDef.where) {
|
|
338
|
+
events = events.filter(viewDef.where);
|
|
339
|
+
}
|
|
340
|
+
// Compute new data
|
|
341
|
+
const newData = computeAggregates(events, viewDef.compute, viewDef.groupBy);
|
|
342
|
+
// If not incremental, clear existing data
|
|
343
|
+
if (!options?.incremental) {
|
|
344
|
+
storage.viewData.set(viewName, newData);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// Merge with existing
|
|
348
|
+
const existing = storage.viewData.get(viewName) ?? new Map();
|
|
349
|
+
for (const [key, row] of newData) {
|
|
350
|
+
existing.set(key, row);
|
|
351
|
+
}
|
|
352
|
+
storage.viewData.set(viewName, existing);
|
|
353
|
+
}
|
|
354
|
+
// Update metadata
|
|
355
|
+
viewDef.lastRefresh = Date.now();
|
|
356
|
+
viewDef.rowCount = storage.viewData.get(viewName)?.size ?? 0;
|
|
357
|
+
// Update checkpoint to current global sequence number
|
|
358
|
+
storage.checkpoints.set(viewName, globalEventSequence);
|
|
359
|
+
return {
|
|
360
|
+
rowsProcessed: events.length,
|
|
361
|
+
duration: Date.now() - start,
|
|
362
|
+
timestamp: Date.now(),
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
// Create view query builder
|
|
366
|
+
const createQueryBuilder = (viewName) => {
|
|
367
|
+
let whereCondition = null;
|
|
368
|
+
let limitValue = null;
|
|
369
|
+
let offsetValue = null;
|
|
370
|
+
let orderByValue = null;
|
|
371
|
+
const query = {
|
|
372
|
+
where(condition) {
|
|
373
|
+
whereCondition = condition;
|
|
374
|
+
return query;
|
|
375
|
+
},
|
|
376
|
+
limit(n) {
|
|
377
|
+
limitValue = n;
|
|
378
|
+
return query;
|
|
379
|
+
},
|
|
380
|
+
offset(n) {
|
|
381
|
+
offsetValue = n;
|
|
382
|
+
return query;
|
|
383
|
+
},
|
|
384
|
+
orderBy(order) {
|
|
385
|
+
orderByValue = order;
|
|
386
|
+
return query;
|
|
387
|
+
},
|
|
388
|
+
async get() {
|
|
389
|
+
const viewDef = storage.views.get(viewName);
|
|
390
|
+
if (!viewDef) {
|
|
391
|
+
throw new Error(`View '${viewName}' not found`);
|
|
392
|
+
}
|
|
393
|
+
const data = storage.viewData.get(viewName) ?? new Map();
|
|
394
|
+
let results = Array.from(data.values());
|
|
395
|
+
// Apply where filter
|
|
396
|
+
if (whereCondition) {
|
|
397
|
+
if (typeof whereCondition === 'function') {
|
|
398
|
+
results = results.filter(whereCondition);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
results = results.filter(row => matchesFilter(row, whereCondition));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Apply orderBy (query override or view default)
|
|
405
|
+
const orderBy = orderByValue ?? viewDef.orderBy;
|
|
406
|
+
if (orderBy) {
|
|
407
|
+
results.sort((a, b) => {
|
|
408
|
+
for (const [field, dir] of Object.entries(orderBy)) {
|
|
409
|
+
const aVal = a[field];
|
|
410
|
+
const bVal = b[field];
|
|
411
|
+
if (aVal !== bVal) {
|
|
412
|
+
return dir === 'asc' ? aVal - bVal : bVal - aVal;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return 0;
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
// Apply offset
|
|
419
|
+
if (offsetValue !== null && offsetValue > 0) {
|
|
420
|
+
results = results.slice(offsetValue);
|
|
421
|
+
}
|
|
422
|
+
// Apply limit (query override or view default)
|
|
423
|
+
const limit = limitValue ?? viewDef.limit;
|
|
424
|
+
if (limit !== null && limit !== undefined) {
|
|
425
|
+
results = results.slice(0, limit);
|
|
426
|
+
}
|
|
427
|
+
return results;
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
return query;
|
|
431
|
+
};
|
|
432
|
+
// Create view instance
|
|
433
|
+
const createViewInstance = (viewName) => {
|
|
434
|
+
return {
|
|
435
|
+
async get(key, options) {
|
|
436
|
+
const viewDef = storage.views.get(viewName);
|
|
437
|
+
if (!viewDef) {
|
|
438
|
+
throw new Error(`View '${viewName}' not found`);
|
|
439
|
+
}
|
|
440
|
+
// Handle strong consistency
|
|
441
|
+
if (options?.consistency === 'strong') {
|
|
442
|
+
await refreshView(viewName);
|
|
443
|
+
}
|
|
444
|
+
const data = storage.viewData.get(viewName) ?? new Map();
|
|
445
|
+
// Single key lookup - including undefined which maps to 'undefined' string key
|
|
446
|
+
let lookupKey = null;
|
|
447
|
+
if (key === undefined) {
|
|
448
|
+
// Check if there's data with 'undefined' as key (from events with missing group keys)
|
|
449
|
+
// If so, treat as single key lookup, otherwise return all rows
|
|
450
|
+
if (data.has('undefined')) {
|
|
451
|
+
lookupKey = 'undefined';
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else if (typeof key === 'object' && key !== null) {
|
|
455
|
+
// Composite key
|
|
456
|
+
lookupKey = getGroupKey(key, viewDef.groupBy);
|
|
457
|
+
}
|
|
458
|
+
else if (key !== undefined) {
|
|
459
|
+
lookupKey = String(key);
|
|
460
|
+
}
|
|
461
|
+
if (lookupKey === null) {
|
|
462
|
+
// Return all rows
|
|
463
|
+
let results = Array.from(data.values());
|
|
464
|
+
// Apply orderBy
|
|
465
|
+
if (viewDef.orderBy) {
|
|
466
|
+
results.sort((a, b) => {
|
|
467
|
+
for (const [field, dir] of Object.entries(viewDef.orderBy)) {
|
|
468
|
+
const aVal = a[field];
|
|
469
|
+
const bVal = b[field];
|
|
470
|
+
if (aVal !== bVal) {
|
|
471
|
+
return dir === 'asc' ? aVal - bVal : bVal - aVal;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return 0;
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
// Apply limit
|
|
478
|
+
if (viewDef.limit) {
|
|
479
|
+
results = results.slice(0, viewDef.limit);
|
|
480
|
+
}
|
|
481
|
+
return results;
|
|
482
|
+
}
|
|
483
|
+
const row = data.get(lookupKey) ?? null;
|
|
484
|
+
// Add metadata if requested
|
|
485
|
+
if (options?.includeMetadata && row) {
|
|
486
|
+
return {
|
|
487
|
+
...row,
|
|
488
|
+
_metadata: {
|
|
489
|
+
staleness: Date.now() - (viewDef.lastRefresh ?? 0),
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
return row;
|
|
494
|
+
},
|
|
495
|
+
where(condition) {
|
|
496
|
+
const viewDef = storage.views.get(viewName);
|
|
497
|
+
if (!viewDef) {
|
|
498
|
+
throw new Error(`View '${viewName}' not found`);
|
|
499
|
+
}
|
|
500
|
+
return createQueryBuilder(viewName).where(condition);
|
|
501
|
+
},
|
|
502
|
+
limit(n) {
|
|
503
|
+
const viewDef = storage.views.get(viewName);
|
|
504
|
+
if (!viewDef) {
|
|
505
|
+
throw new Error(`View '${viewName}' not found`);
|
|
506
|
+
}
|
|
507
|
+
return createQueryBuilder(viewName).limit(n);
|
|
508
|
+
},
|
|
509
|
+
offset(n) {
|
|
510
|
+
const viewDef = storage.views.get(viewName);
|
|
511
|
+
if (!viewDef) {
|
|
512
|
+
throw new Error(`View '${viewName}' not found`);
|
|
513
|
+
}
|
|
514
|
+
return createQueryBuilder(viewName).offset(n);
|
|
515
|
+
},
|
|
516
|
+
orderBy(order) {
|
|
517
|
+
const viewDef = storage.views.get(viewName);
|
|
518
|
+
if (!viewDef) {
|
|
519
|
+
throw new Error(`View '${viewName}' not found`);
|
|
520
|
+
}
|
|
521
|
+
return createQueryBuilder(viewName).orderBy(order);
|
|
522
|
+
},
|
|
523
|
+
subscribe(callback, options) {
|
|
524
|
+
const viewDef = storage.views.get(viewName);
|
|
525
|
+
if (!viewDef) {
|
|
526
|
+
throw new Error(`View '${viewName}' not found or undefined`);
|
|
527
|
+
}
|
|
528
|
+
if (!subscriptions.has(viewName)) {
|
|
529
|
+
subscriptions.set(viewName, new Set());
|
|
530
|
+
}
|
|
531
|
+
const sub = { callback, options };
|
|
532
|
+
subscriptions.get(viewName).add(sub);
|
|
533
|
+
return {
|
|
534
|
+
unsubscribe() {
|
|
535
|
+
subscriptions.get(viewName)?.delete(sub);
|
|
536
|
+
},
|
|
537
|
+
};
|
|
538
|
+
},
|
|
539
|
+
async refresh(options) {
|
|
540
|
+
const viewDef = storage.views.get(viewName);
|
|
541
|
+
if (!viewDef) {
|
|
542
|
+
throw new Error(`View '${viewName}' not found`);
|
|
543
|
+
}
|
|
544
|
+
return refreshView(viewName, options);
|
|
545
|
+
},
|
|
546
|
+
async info() {
|
|
547
|
+
const viewDef = storage.views.get(viewName);
|
|
548
|
+
if (!viewDef) {
|
|
549
|
+
throw new Error(`View '${viewName}' not found`);
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
name: viewDef.name,
|
|
553
|
+
groupBy: viewDef.groupBy,
|
|
554
|
+
computeFields: Object.keys(viewDef.compute),
|
|
555
|
+
rowCount: viewDef.rowCount,
|
|
556
|
+
lastRefresh: viewDef.lastRefresh,
|
|
557
|
+
};
|
|
558
|
+
},
|
|
559
|
+
async drop() {
|
|
560
|
+
const viewDef = storage.views.get(viewName);
|
|
561
|
+
if (!viewDef) {
|
|
562
|
+
throw new Error(`View '${viewName}' not found`);
|
|
563
|
+
}
|
|
564
|
+
storage.views.delete(viewName);
|
|
565
|
+
storage.viewData.delete(viewName);
|
|
566
|
+
subscriptions.delete(viewName);
|
|
567
|
+
},
|
|
568
|
+
async update(options) {
|
|
569
|
+
const viewDef = storage.views.get(viewName);
|
|
570
|
+
if (!viewDef) {
|
|
571
|
+
throw new Error(`View '${viewName}' not found`);
|
|
572
|
+
}
|
|
573
|
+
// Update definition
|
|
574
|
+
if (options.compute) {
|
|
575
|
+
viewDef.compute = options.compute;
|
|
576
|
+
}
|
|
577
|
+
if (options.orderBy !== undefined) {
|
|
578
|
+
viewDef.orderBy = options.orderBy;
|
|
579
|
+
}
|
|
580
|
+
if (options.limit !== undefined) {
|
|
581
|
+
viewDef.limit = options.limit;
|
|
582
|
+
}
|
|
583
|
+
if (options.where !== undefined) {
|
|
584
|
+
viewDef.where = options.where;
|
|
585
|
+
}
|
|
586
|
+
// Trigger refresh
|
|
587
|
+
await internalHelpers.refreshView(viewName);
|
|
588
|
+
},
|
|
589
|
+
};
|
|
590
|
+
};
|
|
591
|
+
// Internal helpers
|
|
592
|
+
const internalHelpers = {
|
|
593
|
+
get currentTime() {
|
|
594
|
+
return currentTime;
|
|
595
|
+
},
|
|
596
|
+
async simulateTimePass(ms) {
|
|
597
|
+
currentTime += ms;
|
|
598
|
+
// Temporarily patch Date.now to return simulated time
|
|
599
|
+
const originalDateNow = Date.now;
|
|
600
|
+
Date.now = () => currentTime;
|
|
601
|
+
try {
|
|
602
|
+
// Check for expiring views
|
|
603
|
+
for (const [viewName, viewDef] of storage.views) {
|
|
604
|
+
if (viewDef.where) {
|
|
605
|
+
const data = storage.viewData.get(viewName) ?? new Map();
|
|
606
|
+
const sourceKey = `${viewDef.from._type}.${viewDef.from._event}`;
|
|
607
|
+
const allEvents = storage.events.get(sourceKey) ?? [];
|
|
608
|
+
// Re-evaluate which rows should still exist
|
|
609
|
+
for (const [key, row] of data) {
|
|
610
|
+
const groupEvents = allEvents.filter(e => {
|
|
611
|
+
return getGroupKey(e, viewDef.groupBy) === key && viewDef.where(e);
|
|
612
|
+
});
|
|
613
|
+
if (groupEvents.length === 0) {
|
|
614
|
+
// Row should be deleted
|
|
615
|
+
data.delete(key);
|
|
616
|
+
notifySubscribers(viewName, { type: 'delete', row });
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
finally {
|
|
623
|
+
// Restore original Date.now
|
|
624
|
+
Date.now = originalDateNow;
|
|
625
|
+
}
|
|
626
|
+
},
|
|
627
|
+
async directWrite(source, data) {
|
|
628
|
+
if (!storage.events.has(source)) {
|
|
629
|
+
storage.events.set(source, []);
|
|
630
|
+
}
|
|
631
|
+
storage.events.get(source).push(data);
|
|
632
|
+
},
|
|
633
|
+
async getViewStorage(viewName) {
|
|
634
|
+
if (!storage.views.has(viewName)) {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
return storage.viewData.get(viewName) ?? null;
|
|
638
|
+
},
|
|
639
|
+
async refreshView(viewName) {
|
|
640
|
+
await refreshView(viewName);
|
|
641
|
+
},
|
|
642
|
+
disableSource(source) {
|
|
643
|
+
storage.disabledSources.add(source);
|
|
644
|
+
},
|
|
645
|
+
enableSource(source) {
|
|
646
|
+
storage.disabledSources.delete(source);
|
|
647
|
+
},
|
|
648
|
+
async advanceTime(ms) {
|
|
649
|
+
currentTime += ms;
|
|
650
|
+
// Trigger scheduled tasks
|
|
651
|
+
for (const task of scheduledTasks) {
|
|
652
|
+
await task();
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
};
|
|
656
|
+
// Create track proxy
|
|
657
|
+
const trackProxy = new Proxy({}, {
|
|
658
|
+
get(_, eventName) {
|
|
659
|
+
// Return event source for view definitions
|
|
660
|
+
if (eventName.startsWith('_')) {
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
// Create callable that also acts as event source
|
|
664
|
+
const eventSource = Object.assign(async (data, options) => {
|
|
665
|
+
const sourceKey = `track.${eventName}`;
|
|
666
|
+
if (!storage.events.has(sourceKey)) {
|
|
667
|
+
storage.events.set(sourceKey, []);
|
|
668
|
+
}
|
|
669
|
+
storage.events.get(sourceKey).push(data);
|
|
670
|
+
// Record event sequence number (for incremental refresh)
|
|
671
|
+
if (!eventSequenceNumbers.has(sourceKey)) {
|
|
672
|
+
eventSequenceNumbers.set(sourceKey, []);
|
|
673
|
+
}
|
|
674
|
+
eventSequenceNumbers.get(sourceKey).push(++globalEventSequence);
|
|
675
|
+
const result = {};
|
|
676
|
+
// Update relevant views - always update all matching views
|
|
677
|
+
const viewsUpdated = [];
|
|
678
|
+
for (const [viewName, viewDef] of storage.views) {
|
|
679
|
+
if (viewDef.from._event === eventName && viewDef.from._type === 'track') {
|
|
680
|
+
await updateViewData(viewName, viewDef, [data]);
|
|
681
|
+
viewsUpdated.push(viewName);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
if (options?.awaitViews) {
|
|
685
|
+
result.viewsUpdated = viewsUpdated;
|
|
686
|
+
}
|
|
687
|
+
return result;
|
|
688
|
+
}, {
|
|
689
|
+
_type: 'track',
|
|
690
|
+
_event: eventName,
|
|
691
|
+
});
|
|
692
|
+
return eventSource;
|
|
693
|
+
},
|
|
694
|
+
});
|
|
695
|
+
// Create stream proxy
|
|
696
|
+
const streamProxy = {
|
|
697
|
+
from: new Proxy({}, {
|
|
698
|
+
get(_, namespace) {
|
|
699
|
+
return new Proxy({}, {
|
|
700
|
+
get(_, event) {
|
|
701
|
+
return {
|
|
702
|
+
_type: 'stream',
|
|
703
|
+
_event: `${namespace}.${event}`,
|
|
704
|
+
};
|
|
705
|
+
},
|
|
706
|
+
});
|
|
707
|
+
},
|
|
708
|
+
}),
|
|
709
|
+
async emit(event, data) {
|
|
710
|
+
const sourceKey = `stream.${event}`;
|
|
711
|
+
if (!storage.events.has(sourceKey)) {
|
|
712
|
+
storage.events.set(sourceKey, []);
|
|
713
|
+
}
|
|
714
|
+
storage.events.get(sourceKey).push(data);
|
|
715
|
+
// Update relevant views - always update all matching views
|
|
716
|
+
for (const [viewName, viewDef] of storage.views) {
|
|
717
|
+
if (viewDef.from._event === event && viewDef.from._type === 'stream') {
|
|
718
|
+
await updateViewData(viewName, viewDef, [data]);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
},
|
|
722
|
+
async retract(event, eventId) {
|
|
723
|
+
const sourceKey = `stream.${event}`;
|
|
724
|
+
if (!storage.retractedEvents.has(sourceKey)) {
|
|
725
|
+
storage.retractedEvents.set(sourceKey, new Set());
|
|
726
|
+
}
|
|
727
|
+
storage.retractedEvents.get(sourceKey).add(eventId);
|
|
728
|
+
// Remove the event from storage
|
|
729
|
+
const events = storage.events.get(sourceKey) ?? [];
|
|
730
|
+
const idx = events.findIndex(e => e.eventId === eventId);
|
|
731
|
+
if (idx !== -1) {
|
|
732
|
+
const removedEvent = events[idx];
|
|
733
|
+
events.splice(idx, 1);
|
|
734
|
+
// Update views
|
|
735
|
+
for (const [viewName, viewDef] of storage.views) {
|
|
736
|
+
if (viewDef.from._event === event && viewDef.from._type === 'stream') {
|
|
737
|
+
// Recalculate the affected group
|
|
738
|
+
const key = getGroupKey(removedEvent, viewDef.groupBy);
|
|
739
|
+
const groupEvents = events.filter(e => getGroupKey(e, viewDef.groupBy) === key);
|
|
740
|
+
const data = storage.viewData.get(viewName) ?? new Map();
|
|
741
|
+
if (groupEvents.length === 0) {
|
|
742
|
+
data.delete(key);
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
const newRow = { ...parseGroupKey(key, viewDef.groupBy) };
|
|
746
|
+
for (const [fieldName, agg] of Object.entries(viewDef.compute)) {
|
|
747
|
+
newRow[fieldName] = computeAggregate(groupEvents, agg);
|
|
748
|
+
}
|
|
749
|
+
data.set(key, newRow);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
};
|
|
756
|
+
// Create on proxy
|
|
757
|
+
const onProxy = new Proxy({}, {
|
|
758
|
+
get(_, namespace) {
|
|
759
|
+
return new Proxy({}, {
|
|
760
|
+
get(_, event) {
|
|
761
|
+
return (handler) => {
|
|
762
|
+
const key = `${namespace}.${event}`;
|
|
763
|
+
if (!eventHandlers.has(key)) {
|
|
764
|
+
eventHandlers.set(key, []);
|
|
765
|
+
}
|
|
766
|
+
eventHandlers.get(key).push(handler);
|
|
767
|
+
};
|
|
768
|
+
},
|
|
769
|
+
});
|
|
770
|
+
},
|
|
771
|
+
});
|
|
772
|
+
// Create every proxy
|
|
773
|
+
const everyProxy = {
|
|
774
|
+
hour(handler) {
|
|
775
|
+
scheduledTasks.push(handler);
|
|
776
|
+
},
|
|
777
|
+
};
|
|
778
|
+
// Create entity proxy
|
|
779
|
+
const createEntityProxy = (entityType) => {
|
|
780
|
+
return (id) => {
|
|
781
|
+
return new Proxy({}, {
|
|
782
|
+
get(_, event) {
|
|
783
|
+
return async (data) => {
|
|
784
|
+
const key = `${entityType}.${event}`;
|
|
785
|
+
const handlers = eventHandlers.get(key) ?? [];
|
|
786
|
+
for (const handler of handlers) {
|
|
787
|
+
await handler({ ...data, userId: id, [entityType.toLowerCase() + 'Id']: id });
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
},
|
|
791
|
+
});
|
|
792
|
+
};
|
|
793
|
+
};
|
|
794
|
+
// Create view namespace
|
|
795
|
+
const viewNamespace = new Proxy({
|
|
796
|
+
async define(name, def) {
|
|
797
|
+
// Validate name
|
|
798
|
+
if (!name || name.length === 0) {
|
|
799
|
+
throw new Error('View name cannot be empty');
|
|
800
|
+
}
|
|
801
|
+
if (/\s/.test(name)) {
|
|
802
|
+
throw new Error('Invalid view name: cannot contain spaces');
|
|
803
|
+
}
|
|
804
|
+
// Validate required fields
|
|
805
|
+
if (!def.groupBy) {
|
|
806
|
+
throw new Error('View definition must include groupBy');
|
|
807
|
+
}
|
|
808
|
+
if (!def.compute) {
|
|
809
|
+
throw new Error('View definition must include compute');
|
|
810
|
+
}
|
|
811
|
+
// Check for duplicates
|
|
812
|
+
if (storage.views.has(name)) {
|
|
813
|
+
throw new Error(`View '${name}' already exists`);
|
|
814
|
+
}
|
|
815
|
+
// Store the view
|
|
816
|
+
const storedDef = {
|
|
817
|
+
...def,
|
|
818
|
+
name,
|
|
819
|
+
createdAt: Date.now(),
|
|
820
|
+
lastRefresh: null,
|
|
821
|
+
rowCount: 0,
|
|
822
|
+
};
|
|
823
|
+
storage.views.set(name, storedDef);
|
|
824
|
+
// Initialize data storage
|
|
825
|
+
storage.viewData.set(name, new Map());
|
|
826
|
+
},
|
|
827
|
+
async list() {
|
|
828
|
+
return Array.from(storage.views.values());
|
|
829
|
+
},
|
|
830
|
+
}, {
|
|
831
|
+
get(target, prop) {
|
|
832
|
+
if (prop === 'define' || prop === 'list') {
|
|
833
|
+
return target[prop];
|
|
834
|
+
}
|
|
835
|
+
// Return cached view instance (or create new one)
|
|
836
|
+
if (!viewInstanceCache.has(prop)) {
|
|
837
|
+
viewInstanceCache.set(prop, createViewInstance(prop));
|
|
838
|
+
}
|
|
839
|
+
return viewInstanceCache.get(prop);
|
|
840
|
+
},
|
|
841
|
+
});
|
|
842
|
+
// Create context
|
|
843
|
+
const context = {
|
|
844
|
+
view: viewNamespace,
|
|
845
|
+
track: trackProxy,
|
|
846
|
+
stream: streamProxy,
|
|
847
|
+
on: onProxy,
|
|
848
|
+
every: everyProxy,
|
|
849
|
+
Customer: createEntityProxy('Customer'),
|
|
850
|
+
_storage: storage,
|
|
851
|
+
_internal: internalHelpers,
|
|
852
|
+
// Aggregate functions
|
|
853
|
+
sum: (field) => ({ type: 'sum', field }),
|
|
854
|
+
count: () => ({ type: 'count' }),
|
|
855
|
+
avg: (field) => ({ type: 'avg', field }),
|
|
856
|
+
min: (field) => ({ type: 'min', field }),
|
|
857
|
+
max: (field) => ({ type: 'max', field }),
|
|
858
|
+
first: (field) => ({ type: 'first', field }),
|
|
859
|
+
last: (field) => ({ type: 'last', field }),
|
|
860
|
+
countDistinct: (field) => ({ type: 'countDistinct', field }),
|
|
861
|
+
};
|
|
862
|
+
return context;
|
|
863
|
+
}
|
|
864
|
+
//# sourceMappingURL=context.js.map
|