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.
Files changed (667) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +446 -315
  3. package/cli/README.md +238 -0
  4. package/cli/agent.ts +72 -0
  5. package/cli/bin.js +44 -0
  6. package/cli/bin.ts +38 -0
  7. package/cli/build.ts +157 -0
  8. package/cli/commands/auth/login.ts +14 -0
  9. package/cli/commands/auth/logout.ts +6 -0
  10. package/cli/commands/auth/whoami.ts +16 -0
  11. package/cli/commands/deploy-multi.ts +245 -0
  12. package/cli/commands/dev/deploy.ts +100 -0
  13. package/cli/commands/dev/dev.ts +95 -0
  14. package/cli/commands/dev/logs.ts +91 -0
  15. package/cli/commands/dev-local.ts +88 -0
  16. package/cli/commands/do-ops.ts +314 -0
  17. package/cli/commands/index.ts +100 -0
  18. package/cli/commands/init.ts +247 -0
  19. package/cli/commands/introspect/emitter.ts +315 -0
  20. package/cli/commands/introspect/index.ts +193 -0
  21. package/cli/commands/link.ts +598 -0
  22. package/cli/commands/snippets.ts +415 -0
  23. package/cli/commands/tunnel.ts +239 -0
  24. package/cli/device-auth.ts +289 -0
  25. package/cli/fallback.ts +12 -0
  26. package/cli/index.ts +121 -0
  27. package/cli/main.ts +246 -0
  28. package/cli/mcp-stdio.ts +790 -0
  29. package/cli/package.json +62 -0
  30. package/cli/runtime/do-registry.ts +193 -0
  31. package/cli/runtime/embedded-db.ts +344 -0
  32. package/cli/runtime/index.ts +9 -0
  33. package/cli/runtime/miniflare-adapter.ts +162 -0
  34. package/cli/sandbox.ts +82 -0
  35. package/cli/src/args.ts +174 -0
  36. package/cli/src/auth.ts +55 -0
  37. package/cli/src/commands/call.ts +84 -0
  38. package/cli/src/commands/charge.ts +96 -0
  39. package/cli/src/commands/config.ts +115 -0
  40. package/cli/src/commands/email.ts +112 -0
  41. package/cli/src/commands/llm.ts +115 -0
  42. package/cli/src/commands/queue.ts +134 -0
  43. package/cli/src/commands/text.ts +86 -0
  44. package/cli/src/config.ts +185 -0
  45. package/cli/src/output.ts +246 -0
  46. package/cli/src/rpc.ts +192 -0
  47. package/cli/utils/config.ts +282 -0
  48. package/cli/utils/detect.ts +73 -0
  49. package/cli/utils/index.ts +15 -0
  50. package/cli/utils/logger.ts +232 -0
  51. package/dist/ai/index.js +19 -0
  52. package/dist/ai/index.js.map +1 -0
  53. package/dist/ai/template-literals.js +852 -0
  54. package/dist/ai/template-literals.js.map +1 -0
  55. package/dist/api/middleware/auth-federation.js +573 -0
  56. package/dist/api/middleware/auth-federation.js.map +1 -0
  57. package/dist/api/middleware/auth.js +545 -0
  58. package/dist/api/middleware/auth.js.map +1 -0
  59. package/dist/db/actions.js +212 -0
  60. package/dist/db/actions.js.map +1 -0
  61. package/dist/db/auth.js +506 -0
  62. package/dist/db/auth.js.map +1 -0
  63. package/dist/db/branches.js +65 -0
  64. package/dist/db/branches.js.map +1 -0
  65. package/dist/db/clickhouse.js +1074 -0
  66. package/dist/db/clickhouse.js.map +1 -0
  67. package/dist/db/dlq.js +39 -0
  68. package/dist/db/dlq.js.map +1 -0
  69. package/dist/db/events.js +28 -0
  70. package/dist/db/events.js.map +1 -0
  71. package/dist/db/exec.js +64 -0
  72. package/dist/db/exec.js.map +1 -0
  73. package/dist/db/files.js +85 -0
  74. package/dist/db/files.js.map +1 -0
  75. package/dist/db/flags.js +24 -0
  76. package/dist/db/flags.js.map +1 -0
  77. package/dist/db/git.js +116 -0
  78. package/dist/db/git.js.map +1 -0
  79. package/dist/db/iceberg/inverted-index.js +862 -0
  80. package/dist/db/iceberg/inverted-index.js.map +1 -0
  81. package/dist/db/iceberg/puffin.js +878 -0
  82. package/dist/db/iceberg/puffin.js.map +1 -0
  83. package/dist/db/iceberg/search-manifest.js +422 -0
  84. package/dist/db/iceberg/search-manifest.js.map +1 -0
  85. package/dist/db/iceberg/types.js +8 -0
  86. package/dist/db/iceberg/types.js.map +1 -0
  87. package/dist/db/index.js +121 -0
  88. package/dist/db/index.js.map +1 -0
  89. package/dist/db/integrations.js +368 -0
  90. package/dist/db/integrations.js.map +1 -0
  91. package/dist/db/json-indexes.js +332 -0
  92. package/dist/db/json-indexes.js.map +1 -0
  93. package/dist/db/linked-accounts.js +287 -0
  94. package/dist/db/linked-accounts.js.map +1 -0
  95. package/dist/db/nouns.js +183 -0
  96. package/dist/db/nouns.js.map +1 -0
  97. package/dist/db/objects.js +170 -0
  98. package/dist/db/objects.js.map +1 -0
  99. package/dist/db/primitives/dag-scheduler/index.js +869 -0
  100. package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
  101. package/dist/db/primitives/exactly-once-context.js +237 -0
  102. package/dist/db/primitives/exactly-once-context.js.map +1 -0
  103. package/dist/db/primitives/index.js +62 -0
  104. package/dist/db/primitives/index.js.map +1 -0
  105. package/dist/db/primitives/keyed-router.js +145 -0
  106. package/dist/db/primitives/keyed-router.js.map +1 -0
  107. package/dist/db/primitives/observability.js +162 -0
  108. package/dist/db/primitives/observability.js.map +1 -0
  109. package/dist/db/primitives/schema-evolution.js +643 -0
  110. package/dist/db/primitives/schema-evolution.js.map +1 -0
  111. package/dist/db/primitives/stateful-operator/index.js +770 -0
  112. package/dist/db/primitives/stateful-operator/index.js.map +1 -0
  113. package/dist/db/primitives/temporal-store.js +306 -0
  114. package/dist/db/primitives/temporal-store.js.map +1 -0
  115. package/dist/db/primitives/typed-column-store.js +1229 -0
  116. package/dist/db/primitives/typed-column-store.js.map +1 -0
  117. package/dist/db/primitives/utils/duration.js +162 -0
  118. package/dist/db/primitives/utils/duration.js.map +1 -0
  119. package/dist/db/primitives/utils/murmur3.js +116 -0
  120. package/dist/db/primitives/utils/murmur3.js.map +1 -0
  121. package/dist/db/primitives/watermark-service.js +136 -0
  122. package/dist/db/primitives/watermark-service.js.map +1 -0
  123. package/dist/db/primitives/window-manager.js +764 -0
  124. package/dist/db/primitives/window-manager.js.map +1 -0
  125. package/dist/db/relationships.js +66 -0
  126. package/dist/db/relationships.js.map +1 -0
  127. package/dist/db/schema-minimal.js +61 -0
  128. package/dist/db/schema-minimal.js.map +1 -0
  129. package/dist/db/search.js +28 -0
  130. package/dist/db/search.js.map +1 -0
  131. package/dist/db/stores.js +1665 -0
  132. package/dist/db/stores.js.map +1 -0
  133. package/dist/db/things.js +297 -0
  134. package/dist/db/things.js.map +1 -0
  135. package/dist/db/vault.js +171 -0
  136. package/dist/db/vault.js.map +1 -0
  137. package/dist/db/verbs.js +102 -0
  138. package/dist/db/verbs.js.map +1 -0
  139. package/dist/do/base.js +48 -0
  140. package/dist/do/base.js.map +1 -0
  141. package/dist/do/tiny.js +31 -0
  142. package/dist/do/tiny.js.map +1 -0
  143. package/dist/lib/DOAuth.js +261 -0
  144. package/dist/lib/DOAuth.js.map +1 -0
  145. package/dist/lib/DODispatcher.js +72 -0
  146. package/dist/lib/DODispatcher.js.map +1 -0
  147. package/dist/lib/Modifier.js +189 -0
  148. package/dist/lib/Modifier.js.map +1 -0
  149. package/dist/lib/StateStorage.js +403 -0
  150. package/dist/lib/StateStorage.js.map +1 -0
  151. package/dist/lib/TypeRegistry.js +122 -0
  152. package/dist/lib/TypeRegistry.js.map +1 -0
  153. package/dist/lib/ai/gateway.js +247 -0
  154. package/dist/lib/ai/gateway.js.map +1 -0
  155. package/dist/lib/ai/tool-loop-agent.js +591 -0
  156. package/dist/lib/ai/tool-loop-agent.js.map +1 -0
  157. package/dist/lib/auto-wiring.js +439 -0
  158. package/dist/lib/auto-wiring.js.map +1 -0
  159. package/dist/lib/browse/browserbase.js +163 -0
  160. package/dist/lib/browse/browserbase.js.map +1 -0
  161. package/dist/lib/browse/cloudflare.js +144 -0
  162. package/dist/lib/browse/cloudflare.js.map +1 -0
  163. package/dist/lib/browse/index.js +62 -0
  164. package/dist/lib/browse/index.js.map +1 -0
  165. package/dist/lib/browse/types.js +13 -0
  166. package/dist/lib/browse/types.js.map +1 -0
  167. package/dist/lib/cache/index.js +37 -0
  168. package/dist/lib/cache/index.js.map +1 -0
  169. package/dist/lib/cache/visibility.js +638 -0
  170. package/dist/lib/cache/visibility.js.map +1 -0
  171. package/dist/lib/capabilities.js +268 -0
  172. package/dist/lib/capabilities.js.map +1 -0
  173. package/dist/lib/channels/base.js +106 -0
  174. package/dist/lib/channels/base.js.map +1 -0
  175. package/dist/lib/channels/discord.js +94 -0
  176. package/dist/lib/channels/discord.js.map +1 -0
  177. package/dist/lib/channels/email.js +204 -0
  178. package/dist/lib/channels/email.js.map +1 -0
  179. package/dist/lib/channels/index.js +90 -0
  180. package/dist/lib/channels/index.js.map +1 -0
  181. package/dist/lib/channels/mdxui-chat.js +95 -0
  182. package/dist/lib/channels/mdxui-chat.js.map +1 -0
  183. package/dist/lib/channels/slack-blockkit.js +121 -0
  184. package/dist/lib/channels/slack-blockkit.js.map +1 -0
  185. package/dist/lib/channels/types.js +7 -0
  186. package/dist/lib/channels/types.js.map +1 -0
  187. package/dist/lib/cloudflare/ai.js +654 -0
  188. package/dist/lib/cloudflare/ai.js.map +1 -0
  189. package/dist/lib/cloudflare/index.js +88 -0
  190. package/dist/lib/cloudflare/index.js.map +1 -0
  191. package/dist/lib/cloudflare/kv.js +342 -0
  192. package/dist/lib/cloudflare/kv.js.map +1 -0
  193. package/dist/lib/cloudflare/queues.js +434 -0
  194. package/dist/lib/cloudflare/queues.js.map +1 -0
  195. package/dist/lib/cloudflare/r2.js +604 -0
  196. package/dist/lib/cloudflare/r2.js.map +1 -0
  197. package/dist/lib/cloudflare/vectorize.js +494 -0
  198. package/dist/lib/cloudflare/vectorize.js.map +1 -0
  199. package/dist/lib/cloudflare/workflows.js +569 -0
  200. package/dist/lib/cloudflare/workflows.js.map +1 -0
  201. package/dist/lib/colo/caching.js +196 -0
  202. package/dist/lib/colo/caching.js.map +1 -0
  203. package/dist/lib/colo/detection.js +194 -0
  204. package/dist/lib/colo/detection.js.map +1 -0
  205. package/dist/lib/colo/external-data.js +219 -0
  206. package/dist/lib/colo/external-data.js.map +1 -0
  207. package/dist/lib/colo/globe-data.js +179 -0
  208. package/dist/lib/colo/globe-data.js.map +1 -0
  209. package/dist/lib/colo/index.js +16 -0
  210. package/dist/lib/colo/index.js.map +1 -0
  211. package/dist/lib/decorators.js +37 -0
  212. package/dist/lib/decorators.js.map +1 -0
  213. package/dist/lib/discovery.js +81 -0
  214. package/dist/lib/discovery.js.map +1 -0
  215. package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
  216. package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
  217. package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
  218. package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
  219. package/dist/lib/executors/CascadeExecutor.js +418 -0
  220. package/dist/lib/executors/CascadeExecutor.js.map +1 -0
  221. package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
  222. package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
  223. package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
  224. package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
  225. package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
  226. package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
  227. package/dist/lib/executors/ParallelStepExecutor.js +308 -0
  228. package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
  229. package/dist/lib/executors/types.js +12 -0
  230. package/dist/lib/executors/types.js.map +1 -0
  231. package/dist/lib/experiments.js +89 -0
  232. package/dist/lib/experiments.js.map +1 -0
  233. package/dist/lib/flags/store.js +262 -0
  234. package/dist/lib/flags/store.js.map +1 -0
  235. package/dist/lib/functions/FunctionComposition.js +467 -0
  236. package/dist/lib/functions/FunctionComposition.js.map +1 -0
  237. package/dist/lib/functions/FunctionMiddleware.js +457 -0
  238. package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
  239. package/dist/lib/functions/FunctionRegistry.js +426 -0
  240. package/dist/lib/functions/FunctionRegistry.js.map +1 -0
  241. package/dist/lib/functions/createFunction.js +1048 -0
  242. package/dist/lib/functions/createFunction.js.map +1 -0
  243. package/dist/lib/humans/index.js +68 -0
  244. package/dist/lib/humans/index.js.map +1 -0
  245. package/dist/lib/humans/templates.js +117 -0
  246. package/dist/lib/humans/templates.js.map +1 -0
  247. package/dist/lib/identity.js +98 -0
  248. package/dist/lib/identity.js.map +1 -0
  249. package/dist/lib/index.js +9 -0
  250. package/dist/lib/index.js.map +1 -0
  251. package/dist/lib/logging/error-logger.js +163 -0
  252. package/dist/lib/logging/error-logger.js.map +1 -0
  253. package/dist/lib/logging/index.js +160 -0
  254. package/dist/lib/logging/index.js.map +1 -0
  255. package/dist/lib/mixins/bash.js +753 -0
  256. package/dist/lib/mixins/bash.js.map +1 -0
  257. package/dist/lib/mixins/fs.js +648 -0
  258. package/dist/lib/mixins/fs.js.map +1 -0
  259. package/dist/lib/mixins/git.js +1006 -0
  260. package/dist/lib/mixins/git.js.map +1 -0
  261. package/dist/lib/mixins/npm.js +662 -0
  262. package/dist/lib/mixins/npm.js.map +1 -0
  263. package/dist/lib/noun-id.js +278 -0
  264. package/dist/lib/noun-id.js.map +1 -0
  265. package/dist/lib/rate-limit/sliding-window.js +148 -0
  266. package/dist/lib/rate-limit/sliding-window.js.map +1 -0
  267. package/dist/lib/rate-limit.js +110 -0
  268. package/dist/lib/rate-limit.js.map +1 -0
  269. package/dist/lib/rpc/bindings.js +548 -0
  270. package/dist/lib/rpc/bindings.js.map +1 -0
  271. package/dist/lib/rpc/index.js +64 -0
  272. package/dist/lib/rpc/index.js.map +1 -0
  273. package/dist/lib/safe-stringify.js +223 -0
  274. package/dist/lib/safe-stringify.js.map +1 -0
  275. package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
  276. package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
  277. package/dist/lib/sqids.js +110 -0
  278. package/dist/lib/sqids.js.map +1 -0
  279. package/dist/lib/sql/adapters/index.js +10 -0
  280. package/dist/lib/sql/adapters/index.js.map +1 -0
  281. package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
  282. package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
  283. package/dist/lib/sql/adapters/pgsql-parser.js +1190 -0
  284. package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
  285. package/dist/lib/sql/index.js +277 -0
  286. package/dist/lib/sql/index.js.map +1 -0
  287. package/dist/lib/sql/types.js +56 -0
  288. package/dist/lib/sql/types.js.map +1 -0
  289. package/dist/lib/type-classifier.js +126 -0
  290. package/dist/lib/type-classifier.js.map +1 -0
  291. package/dist/lib/utils/html.js +47 -0
  292. package/dist/lib/utils/html.js.map +1 -0
  293. package/dist/lib/validation.js +48 -0
  294. package/dist/lib/validation.js.map +1 -0
  295. package/dist/lib/vault/store.js +411 -0
  296. package/dist/lib/vault/store.js.map +1 -0
  297. package/dist/metrics/hunch.js +739 -0
  298. package/dist/metrics/hunch.js.map +1 -0
  299. package/dist/objects/API.js +302 -0
  300. package/dist/objects/API.js.map +1 -0
  301. package/dist/objects/Agent.js +179 -0
  302. package/dist/objects/Agent.js.map +1 -0
  303. package/dist/objects/AgenticFunctionExecutor.js +8 -0
  304. package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
  305. package/dist/objects/App.js +83 -0
  306. package/dist/objects/App.js.map +1 -0
  307. package/dist/objects/Browser.js +884 -0
  308. package/dist/objects/Browser.js.map +1 -0
  309. package/dist/objects/Business.js +107 -0
  310. package/dist/objects/Business.js.map +1 -0
  311. package/dist/objects/CLI.js +221 -0
  312. package/dist/objects/CLI.js.map +1 -0
  313. package/dist/objects/CodeFunctionExecutor.js +8 -0
  314. package/dist/objects/CodeFunctionExecutor.js.map +1 -0
  315. package/dist/objects/Collection.js +161 -0
  316. package/dist/objects/Collection.js.map +1 -0
  317. package/dist/objects/DO.js +41 -0
  318. package/dist/objects/DO.js.map +1 -0
  319. package/dist/objects/DOBase.js +2309 -0
  320. package/dist/objects/DOBase.js.map +1 -0
  321. package/dist/objects/DOCache.js +153 -0
  322. package/dist/objects/DOCache.js.map +1 -0
  323. package/dist/objects/DOFull.js +1676 -0
  324. package/dist/objects/DOFull.js.map +1 -0
  325. package/dist/objects/DOTiny.js +207 -0
  326. package/dist/objects/DOTiny.js.map +1 -0
  327. package/dist/objects/Directory.js +199 -0
  328. package/dist/objects/Directory.js.map +1 -0
  329. package/dist/objects/Entity.js +413 -0
  330. package/dist/objects/Entity.js.map +1 -0
  331. package/dist/objects/Function.js +116 -0
  332. package/dist/objects/Function.js.map +1 -0
  333. package/dist/objects/Human.js +231 -0
  334. package/dist/objects/Human.js.map +1 -0
  335. package/dist/objects/HumanFunctionExecutor.js +8 -0
  336. package/dist/objects/HumanFunctionExecutor.js.map +1 -0
  337. package/dist/objects/IcebergMetadataDO.js +938 -0
  338. package/dist/objects/IcebergMetadataDO.js.map +1 -0
  339. package/dist/objects/IntegrationsDO.js +1174 -0
  340. package/dist/objects/IntegrationsDO.js.map +1 -0
  341. package/dist/objects/ObservabilityBroadcaster.js +149 -0
  342. package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
  343. package/dist/objects/Package.js +154 -0
  344. package/dist/objects/Package.js.map +1 -0
  345. package/dist/objects/Product.js +193 -0
  346. package/dist/objects/Product.js.map +1 -0
  347. package/dist/objects/SDK.js +152 -0
  348. package/dist/objects/SDK.js.map +1 -0
  349. package/dist/objects/SaaS.js +235 -0
  350. package/dist/objects/SaaS.js.map +1 -0
  351. package/dist/objects/SandboxDO.js +759 -0
  352. package/dist/objects/SandboxDO.js.map +1 -0
  353. package/dist/objects/Service.js +337 -0
  354. package/dist/objects/Service.js.map +1 -0
  355. package/dist/objects/Site.js +80 -0
  356. package/dist/objects/Site.js.map +1 -0
  357. package/dist/objects/Startup.js +479 -0
  358. package/dist/objects/Startup.js.map +1 -0
  359. package/dist/objects/ThingsDO.js +170 -0
  360. package/dist/objects/ThingsDO.js.map +1 -0
  361. package/dist/objects/VectorShardDO.js +650 -0
  362. package/dist/objects/VectorShardDO.js.map +1 -0
  363. package/dist/objects/Worker.js +144 -0
  364. package/dist/objects/Worker.js.map +1 -0
  365. package/dist/objects/Workflow.js +196 -0
  366. package/dist/objects/Workflow.js.map +1 -0
  367. package/dist/objects/WorkflowFactory.js +313 -0
  368. package/dist/objects/WorkflowFactory.js.map +1 -0
  369. package/dist/objects/WorkflowRuntime.js +863 -0
  370. package/dist/objects/WorkflowRuntime.js.map +1 -0
  371. package/dist/objects/circuit-breaker-bulkhead.js +178 -0
  372. package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
  373. package/dist/objects/createFunction.js +934 -0
  374. package/dist/objects/createFunction.js.map +1 -0
  375. package/dist/objects/index.js +80 -0
  376. package/dist/objects/index.js.map +1 -0
  377. package/dist/objects/lifecycle/Branch.js +275 -0
  378. package/dist/objects/lifecycle/Branch.js.map +1 -0
  379. package/dist/objects/lifecycle/Clone.js +1499 -0
  380. package/dist/objects/lifecycle/Clone.js.map +1 -0
  381. package/dist/objects/lifecycle/Compact.js +237 -0
  382. package/dist/objects/lifecycle/Compact.js.map +1 -0
  383. package/dist/objects/lifecycle/Promote.js +476 -0
  384. package/dist/objects/lifecycle/Promote.js.map +1 -0
  385. package/dist/objects/lifecycle/Shard.js +560 -0
  386. package/dist/objects/lifecycle/Shard.js.map +1 -0
  387. package/dist/objects/lifecycle/index.js +15 -0
  388. package/dist/objects/lifecycle/index.js.map +1 -0
  389. package/dist/objects/lifecycle/types.js +33 -0
  390. package/dist/objects/lifecycle/types.js.map +1 -0
  391. package/dist/objects/mixins/infrastructure.js +171 -0
  392. package/dist/objects/mixins/infrastructure.js.map +1 -0
  393. package/dist/objects/modules/StoresModule.js +153 -0
  394. package/dist/objects/modules/StoresModule.js.map +1 -0
  395. package/dist/objects/persistence/checkpoint-manager.js +606 -0
  396. package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
  397. package/dist/objects/persistence/index.js +72 -0
  398. package/dist/objects/persistence/index.js.map +1 -0
  399. package/dist/objects/persistence/migration-runner.js +562 -0
  400. package/dist/objects/persistence/migration-runner.js.map +1 -0
  401. package/dist/objects/persistence/replication-manager.js +501 -0
  402. package/dist/objects/persistence/replication-manager.js.map +1 -0
  403. package/dist/objects/persistence/tiered-storage-manager.js +595 -0
  404. package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
  405. package/dist/objects/persistence/types.js +14 -0
  406. package/dist/objects/persistence/types.js.map +1 -0
  407. package/dist/objects/persistence/wal-manager.js +653 -0
  408. package/dist/objects/persistence/wal-manager.js.map +1 -0
  409. package/dist/objects/presets/index.js +20 -0
  410. package/dist/objects/presets/index.js.map +1 -0
  411. package/dist/objects/presets/primitives.js +188 -0
  412. package/dist/objects/presets/primitives.js.map +1 -0
  413. package/dist/objects/primitives/alarm-adapter.js +141 -0
  414. package/dist/objects/primitives/alarm-adapter.js.map +1 -0
  415. package/dist/objects/primitives/index.js +337 -0
  416. package/dist/objects/primitives/index.js.map +1 -0
  417. package/dist/objects/primitives/storage-adapter.js +182 -0
  418. package/dist/objects/primitives/storage-adapter.js.map +1 -0
  419. package/dist/objects/primitives/with-primitives.js +102 -0
  420. package/dist/objects/primitives/with-primitives.js.map +1 -0
  421. package/dist/objects/services/StoreManager.js +227 -0
  422. package/dist/objects/services/StoreManager.js.map +1 -0
  423. package/dist/objects/services/index.js +13 -0
  424. package/dist/objects/services/index.js.map +1 -0
  425. package/dist/objects/transport/auth-layer.js +1451 -0
  426. package/dist/objects/transport/auth-layer.js.map +1 -0
  427. package/dist/objects/transport/capnweb-target.js +355 -0
  428. package/dist/objects/transport/capnweb-target.js.map +1 -0
  429. package/dist/objects/transport/chain.js +441 -0
  430. package/dist/objects/transport/chain.js.map +1 -0
  431. package/dist/objects/transport/handler.js +58 -0
  432. package/dist/objects/transport/handler.js.map +1 -0
  433. package/dist/objects/transport/index.js +53 -0
  434. package/dist/objects/transport/index.js.map +1 -0
  435. package/dist/objects/transport/mcp-server.js +691 -0
  436. package/dist/objects/transport/mcp-server.js.map +1 -0
  437. package/dist/objects/transport/rest-autowire.js +1508 -0
  438. package/dist/objects/transport/rest-autowire.js.map +1 -0
  439. package/dist/objects/transport/rest-router.js +440 -0
  440. package/dist/objects/transport/rest-router.js.map +1 -0
  441. package/dist/objects/transport/rpc-server.js +1539 -0
  442. package/dist/objects/transport/rpc-server.js.map +1 -0
  443. package/dist/objects/transport/shared.js +576 -0
  444. package/dist/objects/transport/shared.js.map +1 -0
  445. package/dist/objects/transport/sync-engine.js +291 -0
  446. package/dist/objects/transport/sync-engine.js.map +1 -0
  447. package/dist/objects/transport/types.js +8 -0
  448. package/dist/objects/transport/types.js.map +1 -0
  449. package/dist/sandbox/index.js +258 -0
  450. package/dist/sandbox/index.js.map +1 -0
  451. package/dist/snippets/artifacts-config.js +241 -0
  452. package/dist/snippets/artifacts-config.js.map +1 -0
  453. package/dist/snippets/artifacts-ingest.js +832 -0
  454. package/dist/snippets/artifacts-ingest.js.map +1 -0
  455. package/dist/snippets/artifacts-serve.js +1035 -0
  456. package/dist/snippets/artifacts-serve.js.map +1 -0
  457. package/dist/snippets/artifacts-types.js +161 -0
  458. package/dist/snippets/artifacts-types.js.map +1 -0
  459. package/dist/snippets/cache-probe.js +376 -0
  460. package/dist/snippets/cache-probe.js.map +1 -0
  461. package/dist/snippets/cache.js +10 -0
  462. package/dist/snippets/cache.js.map +1 -0
  463. package/dist/snippets/events.js +469 -0
  464. package/dist/snippets/events.js.map +1 -0
  465. package/dist/snippets/index.js +7 -0
  466. package/dist/snippets/index.js.map +1 -0
  467. package/dist/snippets/proxy.js +495 -0
  468. package/dist/snippets/proxy.js.map +1 -0
  469. package/dist/snippets/search.js +1759 -0
  470. package/dist/snippets/search.js.map +1 -0
  471. package/dist/streams/index.js +30 -0
  472. package/dist/streams/index.js.map +1 -0
  473. package/dist/streams/observability.js +68 -0
  474. package/dist/streams/observability.js.map +1 -0
  475. package/dist/types/AI.js +92 -0
  476. package/dist/types/AI.js.map +1 -0
  477. package/dist/types/AIFunction.js +171 -0
  478. package/dist/types/AIFunction.js.map +1 -0
  479. package/dist/types/BrowseVerb.js +89 -0
  480. package/dist/types/BrowseVerb.js.map +1 -0
  481. package/dist/types/Browser.js +31 -0
  482. package/dist/types/Browser.js.map +1 -0
  483. package/dist/types/Chaos.js +15 -0
  484. package/dist/types/Chaos.js.map +1 -0
  485. package/dist/types/CloudflareBindings.js +109 -0
  486. package/dist/types/CloudflareBindings.js.map +1 -0
  487. package/dist/types/Collection.js +50 -0
  488. package/dist/types/Collection.js.map +1 -0
  489. package/dist/types/DO.js +2 -0
  490. package/dist/types/DO.js.map +1 -0
  491. package/dist/types/DOLocation.js +63 -0
  492. package/dist/types/DOLocation.js.map +1 -0
  493. package/dist/types/EventHandler.js +57 -0
  494. package/dist/types/EventHandler.js.map +1 -0
  495. package/dist/types/Experiment.js +33 -0
  496. package/dist/types/Experiment.js.map +1 -0
  497. package/dist/types/Flag.js +57 -0
  498. package/dist/types/Flag.js.map +1 -0
  499. package/dist/types/Lifecycle.js +13 -0
  500. package/dist/types/Lifecycle.js.map +1 -0
  501. package/dist/types/Location.js +169 -0
  502. package/dist/types/Location.js.map +1 -0
  503. package/dist/types/Noun.js +66 -0
  504. package/dist/types/Noun.js.map +1 -0
  505. package/dist/types/SessionEvent.js +194 -0
  506. package/dist/types/SessionEvent.js.map +1 -0
  507. package/dist/types/Thing.js +55 -0
  508. package/dist/types/Thing.js.map +1 -0
  509. package/dist/types/ThingDO.js +153 -0
  510. package/dist/types/ThingDO.js.map +1 -0
  511. package/dist/types/Things.js +2 -0
  512. package/dist/types/Things.js.map +1 -0
  513. package/dist/types/Verb.js +119 -0
  514. package/dist/types/Verb.js.map +1 -0
  515. package/dist/types/WorkflowContext.js +70 -0
  516. package/dist/types/WorkflowContext.js.map +1 -0
  517. package/dist/types/analytics-api.js +13 -0
  518. package/dist/types/analytics-api.js.map +1 -0
  519. package/dist/types/capabilities.js +135 -0
  520. package/dist/types/capabilities.js.map +1 -0
  521. package/dist/types/drizzle.js +12 -0
  522. package/dist/types/drizzle.js.map +1 -0
  523. package/dist/types/event.js +201 -0
  524. package/dist/types/event.js.map +1 -0
  525. package/dist/types/fn.js +12 -0
  526. package/dist/types/fn.js.map +1 -0
  527. package/dist/types/iceberg.js +48 -0
  528. package/dist/types/iceberg.js.map +1 -0
  529. package/dist/types/ids.js +170 -0
  530. package/dist/types/ids.js.map +1 -0
  531. package/dist/types/index.js +41 -0
  532. package/dist/types/index.js.map +1 -0
  533. package/dist/types/introspect.js +54 -0
  534. package/dist/types/introspect.js.map +1 -0
  535. package/dist/types/observability.js +124 -0
  536. package/dist/types/observability.js.map +1 -0
  537. package/dist/types/sync-protocol.js +175 -0
  538. package/dist/types/sync-protocol.js.map +1 -0
  539. package/dist/types/vector.js +13 -0
  540. package/dist/types/vector.js.map +1 -0
  541. package/dist/workflows/ScheduleManager.js +473 -0
  542. package/dist/workflows/ScheduleManager.js.map +1 -0
  543. package/dist/workflows/StepDOBridge.js +149 -0
  544. package/dist/workflows/StepDOBridge.js.map +1 -0
  545. package/dist/workflows/StepResultStorage.js +232 -0
  546. package/dist/workflows/StepResultStorage.js.map +1 -0
  547. package/dist/workflows/WaitForEventManager.js +461 -0
  548. package/dist/workflows/WaitForEventManager.js.map +1 -0
  549. package/dist/workflows/analyzer.js +332 -0
  550. package/dist/workflows/analyzer.js.map +1 -0
  551. package/dist/workflows/compat/activity-router.js +484 -0
  552. package/dist/workflows/compat/activity-router.js.map +1 -0
  553. package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
  554. package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
  555. package/dist/workflows/compat/backends/index.js +14 -0
  556. package/dist/workflows/compat/backends/index.js.map +1 -0
  557. package/dist/workflows/compat/errors/index.js +375 -0
  558. package/dist/workflows/compat/errors/index.js.map +1 -0
  559. package/dist/workflows/compat/index.js +79 -0
  560. package/dist/workflows/compat/index.js.map +1 -0
  561. package/dist/workflows/compat/inngest/index.js +989 -0
  562. package/dist/workflows/compat/inngest/index.js.map +1 -0
  563. package/dist/workflows/compat/qstash/index.js +1263 -0
  564. package/dist/workflows/compat/qstash/index.js.map +1 -0
  565. package/dist/workflows/compat/temporal/activities.js +739 -0
  566. package/dist/workflows/compat/temporal/activities.js.map +1 -0
  567. package/dist/workflows/compat/temporal/child-workflows.js +154 -0
  568. package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
  569. package/dist/workflows/compat/temporal/client.js +381 -0
  570. package/dist/workflows/compat/temporal/client.js.map +1 -0
  571. package/dist/workflows/compat/temporal/context.js +309 -0
  572. package/dist/workflows/compat/temporal/context.js.map +1 -0
  573. package/dist/workflows/compat/temporal/determinism.js +216 -0
  574. package/dist/workflows/compat/temporal/determinism.js.map +1 -0
  575. package/dist/workflows/compat/temporal/errors.js +128 -0
  576. package/dist/workflows/compat/temporal/errors.js.map +1 -0
  577. package/dist/workflows/compat/temporal/index.js +2464 -0
  578. package/dist/workflows/compat/temporal/index.js.map +1 -0
  579. package/dist/workflows/compat/temporal/saga.js +504 -0
  580. package/dist/workflows/compat/temporal/saga.js.map +1 -0
  581. package/dist/workflows/compat/temporal/signals.js +364 -0
  582. package/dist/workflows/compat/temporal/signals.js.map +1 -0
  583. package/dist/workflows/compat/temporal/storage.js +271 -0
  584. package/dist/workflows/compat/temporal/storage.js.map +1 -0
  585. package/dist/workflows/compat/temporal/timers.js +347 -0
  586. package/dist/workflows/compat/temporal/timers.js.map +1 -0
  587. package/dist/workflows/compat/temporal/types.js +7 -0
  588. package/dist/workflows/compat/temporal/types.js.map +1 -0
  589. package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
  590. package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
  591. package/dist/workflows/compat/trigger/index.js +468 -0
  592. package/dist/workflows/compat/trigger/index.js.map +1 -0
  593. package/dist/workflows/compat/utils/index.js +69 -0
  594. package/dist/workflows/compat/utils/index.js.map +1 -0
  595. package/dist/workflows/context/correlation-capability.js +266 -0
  596. package/dist/workflows/context/correlation-capability.js.map +1 -0
  597. package/dist/workflows/context/correlation.js +484 -0
  598. package/dist/workflows/context/correlation.js.map +1 -0
  599. package/dist/workflows/context/experiment.js +289 -0
  600. package/dist/workflows/context/experiment.js.map +1 -0
  601. package/dist/workflows/context/flag.js +244 -0
  602. package/dist/workflows/context/flag.js.map +1 -0
  603. package/dist/workflows/context/foundation.js +648 -0
  604. package/dist/workflows/context/foundation.js.map +1 -0
  605. package/dist/workflows/context/human-base.js +106 -0
  606. package/dist/workflows/context/human-base.js.map +1 -0
  607. package/dist/workflows/context/human.js +368 -0
  608. package/dist/workflows/context/human.js.map +1 -0
  609. package/dist/workflows/context/measure.js +354 -0
  610. package/dist/workflows/context/measure.js.map +1 -0
  611. package/dist/workflows/context/rate-limit.js +358 -0
  612. package/dist/workflows/context/rate-limit.js.map +1 -0
  613. package/dist/workflows/context/user.js +117 -0
  614. package/dist/workflows/context/user.js.map +1 -0
  615. package/dist/workflows/context/vault.js +360 -0
  616. package/dist/workflows/context/vault.js.map +1 -0
  617. package/dist/workflows/data/entity-events/entity-events.js +489 -0
  618. package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
  619. package/dist/workflows/data/experiment/index.js +599 -0
  620. package/dist/workflows/data/experiment/index.js.map +1 -0
  621. package/dist/workflows/data/goal/context.js +558 -0
  622. package/dist/workflows/data/goal/context.js.map +1 -0
  623. package/dist/workflows/data/goal/index.js +32 -0
  624. package/dist/workflows/data/goal/index.js.map +1 -0
  625. package/dist/workflows/data/measure/index.js +840 -0
  626. package/dist/workflows/data/measure/index.js.map +1 -0
  627. package/dist/workflows/data/stream/index.js +1149 -0
  628. package/dist/workflows/data/stream/index.js.map +1 -0
  629. package/dist/workflows/data/track/context.js +883 -0
  630. package/dist/workflows/data/track/context.js.map +1 -0
  631. package/dist/workflows/data/track/index.js +15 -0
  632. package/dist/workflows/data/track/index.js.map +1 -0
  633. package/dist/workflows/data/view/context.js +864 -0
  634. package/dist/workflows/data/view/context.js.map +1 -0
  635. package/dist/workflows/domain.js +93 -0
  636. package/dist/workflows/domain.js.map +1 -0
  637. package/dist/workflows/flag.js +176 -0
  638. package/dist/workflows/flag.js.map +1 -0
  639. package/dist/workflows/flags.js +217 -0
  640. package/dist/workflows/flags.js.map +1 -0
  641. package/dist/workflows/hash.js +209 -0
  642. package/dist/workflows/hash.js.map +1 -0
  643. package/dist/workflows/index.js +50 -0
  644. package/dist/workflows/index.js.map +1 -0
  645. package/dist/workflows/on.js +378 -0
  646. package/dist/workflows/on.js.map +1 -0
  647. package/dist/workflows/pipeline-promise.js +481 -0
  648. package/dist/workflows/pipeline-promise.js.map +1 -0
  649. package/dist/workflows/pipeline-types.js +20 -0
  650. package/dist/workflows/pipeline-types.js.map +1 -0
  651. package/dist/workflows/proxy.js +76 -0
  652. package/dist/workflows/proxy.js.map +1 -0
  653. package/dist/workflows/runtime.js +310 -0
  654. package/dist/workflows/runtime.js.map +1 -0
  655. package/dist/workflows/schedule-builder.js +327 -0
  656. package/dist/workflows/schedule-builder.js.map +1 -0
  657. package/dist/workflows/visibility/index.js +146 -0
  658. package/dist/workflows/visibility/index.js.map +1 -0
  659. package/dist/workflows/visibility/query-parser.js +150 -0
  660. package/dist/workflows/visibility/query-parser.js.map +1 -0
  661. package/dist/workflows/visibility/store.js +223 -0
  662. package/dist/workflows/visibility/store.js.map +1 -0
  663. package/dist/workflows/visibility/types.js +30 -0
  664. package/dist/workflows/visibility/types.js.map +1 -0
  665. package/dist/workflows/workflow.js +53 -0
  666. package/dist/workflows/workflow.js.map +1 -0
  667. package/package.json +294 -46
@@ -0,0 +1,1149 @@
1
+ /**
2
+ * Stream Processing API ($.stream)
3
+ *
4
+ * Provides real-time stream processing capabilities:
5
+ * - Stream sources from domain events, tracked events, and measurements
6
+ * - Transformations: filter(), map(), enrich(), flatMap()
7
+ * - Keyed streams via keyBy()
8
+ * - Windowing: tumbling, sliding, session windows
9
+ * - Aggregations within windows
10
+ * - Stream joins with temporal constraints
11
+ * - Sinks to track, measure, and view
12
+ *
13
+ * @module workflows/data/stream
14
+ */
15
+ import { toMillis } from '../../../db/primitives/utils/duration';
16
+ // ============================================================================
17
+ // Implementation
18
+ // ============================================================================
19
+ class StreamImpl {
20
+ type = 'stream';
21
+ source;
22
+ sink;
23
+ bufferCapacity;
24
+ bufferStrategy;
25
+ subscribers = [];
26
+ errorHandlers = [];
27
+ deadLetterHandlers = [];
28
+ forEachHandler;
29
+ running = false; // Streams don't run until explicitly started
30
+ streamName;
31
+ maxRetries = 0;
32
+ _bufferCapacity = Infinity;
33
+ _bufferStrategy = 'dropOldest';
34
+ _buffer = []; // Renamed to avoid conflict with buffer() method
35
+ throttleMs = 0;
36
+ lastEmitTime = 0;
37
+ throttleQueue = [];
38
+ throttleTimer = null;
39
+ ctx;
40
+ pipeline = [];
41
+ keyedSubscribers = [];
42
+ started = false; // Track if start() was called
43
+ isRoot = true; // Whether this is a root stream (receives from emit directly)
44
+ parentStream; // Parent stream for child streams
45
+ pendingOperations = []; // Track pending async operations
46
+ constructor(source, ctx, parent) {
47
+ this.source = Object.freeze({ ...source });
48
+ this.ctx = ctx;
49
+ if (parent) {
50
+ this.isRoot = false;
51
+ this.parentStream = parent;
52
+ }
53
+ }
54
+ isRootStream() {
55
+ return this.isRoot;
56
+ }
57
+ filter(predicate) {
58
+ const newStream = new StreamImpl(this.source, this.ctx, this);
59
+ newStream.pipeline.push(async (item) => {
60
+ const result = await predicate(item);
61
+ if (!result)
62
+ return Symbol.for('skip');
63
+ return item;
64
+ });
65
+ // Subscribe to parent to receive items, tracking async operations
66
+ this.subscribe((item) => {
67
+ const op = newStream.processItem(item);
68
+ newStream.pendingOperations.push(op);
69
+ });
70
+ this.ctx.registerStream(newStream);
71
+ return newStream;
72
+ }
73
+ map(fn) {
74
+ const newStream = new StreamImpl(this.source, this.ctx, this);
75
+ newStream.pipeline.push(async (item) => {
76
+ return await fn(item);
77
+ });
78
+ // Subscribe to parent to receive items, tracking async operations
79
+ this.subscribe((item) => {
80
+ const op = newStream.processItem(item);
81
+ newStream.pendingOperations.push(op);
82
+ });
83
+ this.ctx.registerStream(newStream);
84
+ return newStream;
85
+ }
86
+ flatMap(fn) {
87
+ const newStream = new StreamImpl(this.source, this.ctx, this);
88
+ newStream.pipeline.push(async (item) => {
89
+ const result = await fn(item);
90
+ return { __flatMap: result };
91
+ });
92
+ // Subscribe to parent to receive items, tracking async operations
93
+ this.subscribe((item) => {
94
+ const op = newStream.processItem(item);
95
+ newStream.pendingOperations.push(op);
96
+ });
97
+ this.ctx.registerStream(newStream);
98
+ return newStream;
99
+ }
100
+ enrich(fn) {
101
+ const newStream = new StreamImpl(this.source, this.ctx, this);
102
+ newStream.pipeline.push(async (item) => {
103
+ return await fn(item, this.ctx);
104
+ });
105
+ // Subscribe to parent to receive items, tracking async operations
106
+ this.subscribe((item) => {
107
+ const op = newStream.processItem(item);
108
+ newStream.pendingOperations.push(op);
109
+ });
110
+ this.ctx.registerStream(newStream);
111
+ return newStream;
112
+ }
113
+ keyBy(keyOrFn) {
114
+ return new KeyedStreamImpl(this, keyOrFn, this.ctx);
115
+ }
116
+ // These methods exist to provide helpful error messages
117
+ join() {
118
+ throw new Error('join() requires a keyed stream. Call keyBy() first.');
119
+ }
120
+ leftJoin() {
121
+ throw new Error('leftJoin() requires a keyed stream. Call keyBy() first.');
122
+ }
123
+ coGroup() {
124
+ throw new Error('coGroup() requires a keyed stream. Call keyBy() first.');
125
+ }
126
+ get window() {
127
+ // For non-keyed streams, use global key
128
+ const globalKeyedStream = new KeyedStreamImpl(this, () => '__global__', this.ctx);
129
+ return {
130
+ tumbling: (size) => {
131
+ const ws = globalKeyedStream.window.tumbling(size);
132
+ ws.key = '__global__';
133
+ return ws;
134
+ },
135
+ sliding: (size, slide) => globalKeyedStream.window.sliding(size, slide),
136
+ session: (gap) => globalKeyedStream.window.session(gap),
137
+ };
138
+ }
139
+ subscribe(fn) {
140
+ this.subscribers.push(fn);
141
+ // Auto-start when subscribed (implicit running) unless explicitly stopped
142
+ if (!this.started) {
143
+ this.running = true;
144
+ }
145
+ return () => {
146
+ const idx = this.subscribers.indexOf(fn);
147
+ if (idx !== -1)
148
+ this.subscribers.splice(idx, 1);
149
+ };
150
+ }
151
+ forEach(fn) {
152
+ this.forEachHandler = fn;
153
+ // Auto-start when forEach is called
154
+ if (!this.started) {
155
+ this.running = true;
156
+ }
157
+ return this;
158
+ }
159
+ async flush() {
160
+ // First, flush parent stream if we have one (to ensure upstream items flow through)
161
+ if (this.parentStream) {
162
+ await this.parentStream.flush();
163
+ }
164
+ // Wait for all pending async operations on THIS stream
165
+ // Keep flushing until no more pending operations (items may chain through)
166
+ while (this.pendingOperations.length > 0) {
167
+ const ops = this.pendingOperations;
168
+ this.pendingOperations = [];
169
+ await Promise.all(ops);
170
+ }
171
+ // Advance time to trigger window closes
172
+ this.ctx.advanceTime(Date.now());
173
+ // Process any throttled items
174
+ if (this.throttleTimer) {
175
+ clearTimeout(this.throttleTimer);
176
+ this.throttleTimer = null;
177
+ }
178
+ for (const item of this.throttleQueue) {
179
+ await this.deliverItem(item);
180
+ }
181
+ this.throttleQueue = [];
182
+ }
183
+ async start() {
184
+ this.started = true;
185
+ this.running = true;
186
+ }
187
+ async stop() {
188
+ this.running = false;
189
+ }
190
+ isRunning() {
191
+ return this.started && this.running;
192
+ }
193
+ name(n) {
194
+ this.streamName = n;
195
+ this.ctx.namedStreams.set(n, this);
196
+ return this;
197
+ }
198
+ getName() {
199
+ return this.streamName;
200
+ }
201
+ onError(handler) {
202
+ this.errorHandlers.push(handler);
203
+ return this;
204
+ }
205
+ deadLetter(handler) {
206
+ this.deadLetterHandlers.push(handler);
207
+ return this;
208
+ }
209
+ retry(maxRetries) {
210
+ this.maxRetries = maxRetries;
211
+ return this;
212
+ }
213
+ buffer(capacity, options) {
214
+ this._bufferCapacity = capacity;
215
+ this.bufferCapacity = capacity;
216
+ this._bufferStrategy = options?.strategy ?? 'dropOldest';
217
+ this.bufferStrategy = this._bufferStrategy;
218
+ return this;
219
+ }
220
+ throttle(interval) {
221
+ this.throttleMs = toMillis(interval);
222
+ return this;
223
+ }
224
+ get to() {
225
+ const self = this;
226
+ return {
227
+ track: new Proxy({}, {
228
+ get(_, event) {
229
+ self.sink = { type: 'track', event };
230
+ self.ctx.registerSinkStream(self, 'track', event);
231
+ return self;
232
+ },
233
+ }),
234
+ measure: new Proxy({}, {
235
+ get(_, metric) {
236
+ self.sink = { type: 'measure', metric };
237
+ self.ctx.registerSinkStream(self, 'measure', metric);
238
+ return self;
239
+ },
240
+ }),
241
+ view: new Proxy({}, {
242
+ get(_, view) {
243
+ self.sink = { type: 'view', view };
244
+ self.ctx.registerSinkStream(self, 'view', view);
245
+ return self;
246
+ },
247
+ }),
248
+ };
249
+ }
250
+ async processItem(item) {
251
+ // If explicitly stopped (started = true but running = false), don't process
252
+ if (this.started && !this.running) {
253
+ return;
254
+ }
255
+ // Otherwise, process if:
256
+ // - root stream (always processes unless explicitly stopped)
257
+ // - has subscribers
258
+ // - has forEachHandler
259
+ // - has pipeline (predicates/transforms to run for side effects like spying)
260
+ if (!this.isRoot && this.subscribers.length === 0 && !this.forEachHandler && this.pipeline.length === 0) {
261
+ return;
262
+ }
263
+ let current = item;
264
+ let attempts = 0;
265
+ const maxAttempts = this.maxRetries + 1;
266
+ while (attempts < maxAttempts) {
267
+ try {
268
+ // Process through pipeline
269
+ for (const step of this.pipeline) {
270
+ current = await step(current);
271
+ if (current === Symbol.for('skip'))
272
+ return;
273
+ if (current && typeof current === 'object' && '__flatMap' in current) {
274
+ const items = current.__flatMap;
275
+ for (const flatItem of items) {
276
+ await this.deliverItem(flatItem);
277
+ }
278
+ return;
279
+ }
280
+ }
281
+ await this.deliverItem(current);
282
+ return;
283
+ }
284
+ catch (error) {
285
+ attempts++;
286
+ if (attempts >= maxAttempts) {
287
+ for (const handler of this.errorHandlers) {
288
+ handler(error);
289
+ }
290
+ for (const handler of this.deadLetterHandlers) {
291
+ handler(item, error);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ }
297
+ async deliverItem(item) {
298
+ // Handle throttling
299
+ if (this.throttleMs > 0) {
300
+ const now = Date.now();
301
+ if (now - this.lastEmitTime < this.throttleMs) {
302
+ this.throttleQueue.push(item);
303
+ if (!this.throttleTimer) {
304
+ this.throttleTimer = setTimeout(() => {
305
+ const next = this.throttleQueue.shift();
306
+ if (next)
307
+ this.deliverItem(next);
308
+ this.throttleTimer = null;
309
+ }, this.throttleMs - (now - this.lastEmitTime));
310
+ }
311
+ return;
312
+ }
313
+ this.lastEmitTime = now;
314
+ }
315
+ // Handle buffering
316
+ if (this._bufferCapacity < Infinity) {
317
+ this._buffer.push(item);
318
+ if (this._buffer.length > this._bufferCapacity) {
319
+ if (this._bufferStrategy === 'dropOldest') {
320
+ this._buffer.shift();
321
+ }
322
+ else {
323
+ this._buffer.pop();
324
+ return; // Drop newest means don't deliver this one
325
+ }
326
+ }
327
+ }
328
+ for (const subscriber of this.subscribers) {
329
+ subscriber(item);
330
+ }
331
+ if (this.forEachHandler) {
332
+ await this.forEachHandler(item);
333
+ }
334
+ }
335
+ }
336
+ class KeyedStreamImpl {
337
+ type = 'keyed-stream';
338
+ keySelector;
339
+ parentStream;
340
+ ctx;
341
+ subscribers = [];
342
+ timestampSubscribers = [];
343
+ constructor(parent, keySelector, ctx) {
344
+ this.parentStream = parent;
345
+ this.keySelector = keySelector;
346
+ this.ctx = ctx;
347
+ // Subscribe to parent stream to get transformed items
348
+ this.parentStream.subscribe((item) => {
349
+ // Get timestamp from item if available, otherwise use current time
350
+ const timestamp = item?.timestamp ?? Date.now();
351
+ this.processItem(item, timestamp);
352
+ });
353
+ this.ctx.registerKeyedStream(this);
354
+ }
355
+ getKey(item) {
356
+ if (typeof this.keySelector === 'string') {
357
+ return item[this.keySelector];
358
+ }
359
+ return this.keySelector(item);
360
+ }
361
+ get window() {
362
+ return {
363
+ tumbling: (size) => {
364
+ const sizeMs = toMillis(size);
365
+ return new WindowedStreamImpl(this, { type: 'tumbling', size: sizeMs }, this.ctx);
366
+ },
367
+ sliding: (size, slide) => {
368
+ const sizeMs = toMillis(size);
369
+ const slideMs = toMillis(slide);
370
+ if (slideMs > sizeMs) {
371
+ throw new Error('Slide cannot be larger than size');
372
+ }
373
+ return new WindowedStreamImpl(this, { type: 'sliding', size: sizeMs, slide: slideMs }, this.ctx);
374
+ },
375
+ session: (gap) => {
376
+ const gapMs = toMillis(gap);
377
+ return new WindowedStreamImpl(this, { type: 'session', gap: gapMs }, this.ctx);
378
+ },
379
+ };
380
+ }
381
+ join(other) {
382
+ return new JoinBuilderImpl(this, other, 'inner', this.ctx);
383
+ }
384
+ leftJoin(other) {
385
+ return new JoinBuilderImpl(this, other, 'left', this.ctx);
386
+ }
387
+ coGroup(other) {
388
+ return new CoGroupBuilderImpl(this, other, this.ctx);
389
+ }
390
+ subscribe(fn) {
391
+ this.subscribers.push(fn);
392
+ return () => {
393
+ const idx = this.subscribers.indexOf(fn);
394
+ if (idx !== -1)
395
+ this.subscribers.splice(idx, 1);
396
+ };
397
+ }
398
+ subscribeWithTimestamp(fn) {
399
+ this.timestampSubscribers.push(fn);
400
+ return () => {
401
+ const idx = this.timestampSubscribers.indexOf(fn);
402
+ if (idx !== -1)
403
+ this.timestampSubscribers.splice(idx, 1);
404
+ };
405
+ }
406
+ async flush() {
407
+ await this.parentStream.flush();
408
+ }
409
+ processItem(item, timestamp) {
410
+ const key = this.getKey(item);
411
+ const ts = timestamp ?? item?.timestamp ?? Date.now();
412
+ for (const subscriber of this.subscribers) {
413
+ subscriber(item, key);
414
+ }
415
+ for (const subscriber of this.timestampSubscribers) {
416
+ subscriber(item, key, ts);
417
+ }
418
+ }
419
+ }
420
+ class WindowedStreamImpl {
421
+ type = 'windowed-stream';
422
+ window;
423
+ key;
424
+ keyedStream;
425
+ ctx;
426
+ windowCloseHandlers = [];
427
+ windowState = new Map();
428
+ subscribers = [];
429
+ aggregateSpec;
430
+ reduceSpec;
431
+ constructor(keyedStream, windowSpec, ctx) {
432
+ this.keyedStream = keyedStream;
433
+ this.window = windowSpec;
434
+ this.ctx = ctx;
435
+ // Subscribe to keyed stream to receive items
436
+ this.keyedStream.subscribeWithTimestamp((item, key, timestamp) => {
437
+ this.processItem(item, timestamp);
438
+ });
439
+ this.ctx.registerWindowedStream(this);
440
+ }
441
+ aggregate(spec) {
442
+ this.aggregateSpec = spec;
443
+ return new AggregatedStreamImpl(this, this.ctx);
444
+ }
445
+ reduce(reducer, initial) {
446
+ this.reduceSpec = { reducer: reducer, initial };
447
+ return new AggregatedStreamImpl(this, this.ctx);
448
+ }
449
+ onWindowClose(handler) {
450
+ this.windowCloseHandlers.push(handler);
451
+ }
452
+ subscribe(fn) {
453
+ this.subscribers.push(fn);
454
+ return () => {
455
+ const idx = this.subscribers.indexOf(fn);
456
+ if (idx !== -1)
457
+ this.subscribers.splice(idx, 1);
458
+ };
459
+ }
460
+ async flush() {
461
+ // Trigger window close for all pending windows
462
+ for (const [windowKey, state] of this.windowState.entries()) {
463
+ const [key] = windowKey.split('|');
464
+ const windowInfo = this.computeWindowInfo(state.lastTimestamp);
465
+ for (const handler of this.windowCloseHandlers) {
466
+ handler(key, state.elements, windowInfo);
467
+ }
468
+ }
469
+ this.windowState.clear();
470
+ }
471
+ computeWindowInfo(timestamp) {
472
+ if (this.window.type === 'tumbling') {
473
+ const size = this.window.size;
474
+ const start = Math.floor(timestamp / size) * size;
475
+ return { start, end: start + size };
476
+ }
477
+ else if (this.window.type === 'sliding') {
478
+ const size = this.window.size;
479
+ const slide = this.window.slide;
480
+ const start = Math.floor(timestamp / slide) * slide;
481
+ return { start, end: start + size };
482
+ }
483
+ else {
484
+ // Session - approximate based on elements
485
+ return { start: timestamp, end: timestamp + (this.window.gap || 0) };
486
+ }
487
+ }
488
+ processItem(item, timestamp) {
489
+ const key = this.keyedStream.getKey(item);
490
+ const windowKeys = this.getWindowKeys(key, timestamp);
491
+ for (const windowKey of windowKeys) {
492
+ let state = this.windowState.get(windowKey);
493
+ if (!state) {
494
+ state = { elements: [], lastTimestamp: timestamp };
495
+ this.windowState.set(windowKey, state);
496
+ }
497
+ state.elements.push(item);
498
+ state.lastTimestamp = Math.max(state.lastTimestamp, timestamp);
499
+ }
500
+ for (const subscriber of this.subscribers) {
501
+ subscriber(item, key);
502
+ }
503
+ }
504
+ getWindowKeys(key, timestamp) {
505
+ if (this.window.type === 'tumbling') {
506
+ const size = this.window.size;
507
+ const windowStart = Math.floor(timestamp / size) * size;
508
+ return [`${key}|${windowStart}`];
509
+ }
510
+ else if (this.window.type === 'session') {
511
+ // For session windows, check if we should start a new session
512
+ const gap = this.window.gap;
513
+ // Find the current session for this key (if any)
514
+ let currentSession = null;
515
+ let currentLastTimestamp = -Infinity;
516
+ for (const [windowKey, state] of this.windowState.entries()) {
517
+ if (windowKey.startsWith(`${key}|session_`)) {
518
+ if (state.lastTimestamp > currentLastTimestamp) {
519
+ currentSession = windowKey;
520
+ currentLastTimestamp = state.lastTimestamp;
521
+ }
522
+ }
523
+ }
524
+ // If there's no current session, or the gap is too large, start a new session
525
+ if (currentSession === null || timestamp - currentLastTimestamp > gap) {
526
+ return [`${key}|session_${timestamp}`];
527
+ }
528
+ // Otherwise, add to the current session
529
+ return [currentSession];
530
+ }
531
+ else {
532
+ // Sliding window: item belongs to all windows where windowStart <= timestamp < windowStart + size
533
+ const size = this.window.size;
534
+ const slide = this.window.slide;
535
+ const keys = [];
536
+ // Find the earliest window that could contain this timestamp
537
+ // Window starts at multiples of slide
538
+ const earliestWindowStart = Math.floor((timestamp - size + 1) / slide) * slide;
539
+ const latestWindowStart = Math.floor(timestamp / slide) * slide;
540
+ for (let windowStart = Math.max(0, earliestWindowStart); windowStart <= latestWindowStart; windowStart += slide) {
541
+ if (timestamp >= windowStart && timestamp < windowStart + size) {
542
+ keys.push(`${key}|${windowStart}`);
543
+ }
544
+ }
545
+ return keys;
546
+ }
547
+ }
548
+ triggerWindowClose(currentTime) {
549
+ const windowsToClose = [];
550
+ for (const [windowKey, state] of this.windowState.entries()) {
551
+ const [key, windowId] = windowKey.split('|');
552
+ let shouldClose = false;
553
+ let windowInfo;
554
+ if (this.window.type === 'tumbling') {
555
+ const size = this.window.size;
556
+ const windowStart = parseInt(windowId);
557
+ const windowEnd = windowStart + size;
558
+ windowInfo = { start: windowStart, end: windowEnd };
559
+ shouldClose = currentTime >= windowEnd;
560
+ }
561
+ else if (this.window.type === 'sliding') {
562
+ const size = this.window.size;
563
+ const slide = this.window.slide;
564
+ const windowStart = parseInt(windowId);
565
+ const windowEnd = windowStart + size;
566
+ windowInfo = { start: windowStart, end: windowEnd };
567
+ shouldClose = currentTime >= windowEnd;
568
+ }
569
+ else {
570
+ // Session
571
+ const gap = this.window.gap;
572
+ windowInfo = { start: state.lastTimestamp - gap, end: state.lastTimestamp + gap };
573
+ shouldClose = currentTime >= state.lastTimestamp + gap;
574
+ }
575
+ if (shouldClose) {
576
+ windowsToClose.push({ key: key, windowKey, state });
577
+ }
578
+ }
579
+ for (const { key, windowKey, state } of windowsToClose) {
580
+ const windowInfo = this.computeWindowInfo(state.lastTimestamp);
581
+ for (const handler of this.windowCloseHandlers) {
582
+ handler(key, state.elements, windowInfo);
583
+ }
584
+ this.windowState.delete(windowKey);
585
+ }
586
+ }
587
+ getAggregateSpec() {
588
+ return this.aggregateSpec;
589
+ }
590
+ getReduceSpec() {
591
+ return this.reduceSpec;
592
+ }
593
+ getWindowState() {
594
+ return this.windowState;
595
+ }
596
+ getKeyedStream() {
597
+ return this.keyedStream;
598
+ }
599
+ }
600
+ class AggregatedStreamImpl {
601
+ type = 'stream';
602
+ sink;
603
+ windowedStream;
604
+ ctx;
605
+ subscribers = [];
606
+ mapFn;
607
+ constructor(windowedStream, ctx) {
608
+ this.windowedStream = windowedStream;
609
+ this.ctx = ctx;
610
+ this.ctx.registerAggregatedStream(this);
611
+ }
612
+ map(fn) {
613
+ const newStream = new AggregatedStreamImpl(this.windowedStream, this.ctx);
614
+ const prevMapFn = this.mapFn;
615
+ newStream.mapFn = (item) => {
616
+ const prev = prevMapFn ? prevMapFn(item) : item;
617
+ return fn(prev);
618
+ };
619
+ return newStream;
620
+ }
621
+ subscribe(fn) {
622
+ this.subscribers.push(fn);
623
+ return () => {
624
+ const idx = this.subscribers.indexOf(fn);
625
+ if (idx !== -1)
626
+ this.subscribers.splice(idx, 1);
627
+ };
628
+ }
629
+ async flush() {
630
+ // Advance time to trigger window closes
631
+ this.ctx.advanceTime(Date.now());
632
+ await this.windowedStream.flush();
633
+ }
634
+ get to() {
635
+ const self = this;
636
+ return {
637
+ track: new Proxy({}, {
638
+ get(_, event) {
639
+ self.sink = { type: 'track', event };
640
+ return self;
641
+ },
642
+ }),
643
+ measure: new Proxy({}, {
644
+ get(_, metric) {
645
+ self.sink = { type: 'measure', metric };
646
+ self.ctx.registerAggregatedSink(self, 'measure', metric);
647
+ return self;
648
+ },
649
+ }),
650
+ view: new Proxy({}, {
651
+ get(_, view) {
652
+ self.sink = { type: 'view', view };
653
+ self.ctx.registerAggregatedSink(self, 'view', view);
654
+ return self;
655
+ },
656
+ }),
657
+ };
658
+ }
659
+ emitResult(result, key, info) {
660
+ let finalResult = result;
661
+ if (this.mapFn) {
662
+ finalResult = this.mapFn(result);
663
+ }
664
+ for (const subscriber of this.subscribers) {
665
+ subscriber(finalResult, key, info);
666
+ }
667
+ }
668
+ getWindowedStream() {
669
+ return this.windowedStream;
670
+ }
671
+ }
672
+ class JoinBuilderImpl {
673
+ type = 'joined-stream';
674
+ window;
675
+ leftStream;
676
+ rightStream;
677
+ joinType;
678
+ ctx;
679
+ constructor(left, right, joinType, ctx) {
680
+ this.leftStream = left;
681
+ this.rightStream = right;
682
+ this.joinType = joinType;
683
+ this.ctx = ctx;
684
+ }
685
+ within(duration) {
686
+ this.window = toMillis(duration);
687
+ return this;
688
+ }
689
+ on(fn) {
690
+ const newStream = new StreamImpl({ type: 'domain' }, this.ctx);
691
+ this.ctx.registerJoin(this.leftStream, this.rightStream, this.window ?? Infinity, this.joinType, fn, newStream);
692
+ return newStream;
693
+ }
694
+ }
695
+ class CoGroupBuilderImpl {
696
+ type = 'joined-stream';
697
+ window;
698
+ leftStream;
699
+ rightStream;
700
+ ctx;
701
+ constructor(left, right, ctx) {
702
+ this.leftStream = left;
703
+ this.rightStream = right;
704
+ this.ctx = ctx;
705
+ }
706
+ within(duration) {
707
+ this.window = toMillis(duration);
708
+ return this;
709
+ }
710
+ apply(fn) {
711
+ const newStream = new StreamImpl({ type: 'domain' }, this.ctx);
712
+ this.ctx.registerCoGroup(this.leftStream, this.rightStream, this.window ?? Infinity, fn, newStream);
713
+ return newStream;
714
+ }
715
+ }
716
+ // ============================================================================
717
+ // Stream Context Implementation
718
+ // ============================================================================
719
+ class StreamContextImpl {
720
+ _storage = {
721
+ customers: new Map(),
722
+ };
723
+ trackHandlers = new Map();
724
+ measureHandlers = new Map();
725
+ entityActionHandlers = new Map();
726
+ streams = [];
727
+ keyedStreams = [];
728
+ windowedStreams = [];
729
+ aggregatedStreams = [];
730
+ namedStreams = new Map();
731
+ eventBuffer = new Map();
732
+ trackEventBuffer = new Map();
733
+ // Sink streams
734
+ sinkStreams = new Map();
735
+ aggregatedSinks = new Map();
736
+ // Joins
737
+ joins = [];
738
+ coGroups = [];
739
+ // Views storage
740
+ viewData = new Map();
741
+ _hooks = {
742
+ onTrack: (event, handler) => {
743
+ if (!this.trackHandlers.has(event))
744
+ this.trackHandlers.set(event, []);
745
+ this.trackHandlers.get(event).push(handler);
746
+ },
747
+ onMeasure: (metric, handler) => {
748
+ if (!this.measureHandlers.has(metric))
749
+ this.measureHandlers.set(metric, []);
750
+ this.measureHandlers.get(metric).push(handler);
751
+ },
752
+ onEntityAction: (entity, action, handler) => {
753
+ const key = `${entity}.${action}`;
754
+ if (!this.entityActionHandlers.has(key))
755
+ this.entityActionHandlers.set(key, []);
756
+ this.entityActionHandlers.get(key).push(handler);
757
+ },
758
+ };
759
+ stream = {
760
+ from: new Proxy({}, {
761
+ get: (_, entity) => {
762
+ if (entity === 'track') {
763
+ return new Proxy({}, {
764
+ get: (_, event) => {
765
+ const stream = new StreamImpl({ type: 'track', event }, this);
766
+ this.registerStream(stream);
767
+ return stream;
768
+ },
769
+ });
770
+ }
771
+ if (entity === 'measure') {
772
+ return new Proxy({}, {
773
+ get: (_, metric) => {
774
+ const stream = new StreamImpl({ type: 'measure', metric }, this);
775
+ this.registerStream(stream);
776
+ return stream;
777
+ },
778
+ });
779
+ }
780
+ return new Proxy({}, {
781
+ get: (_, event) => {
782
+ const stream = new StreamImpl({ type: 'domain', entity, event }, this);
783
+ this.registerStream(stream);
784
+ return stream;
785
+ },
786
+ });
787
+ },
788
+ }),
789
+ emit: async (entity, event, data) => {
790
+ const timestamp = data?.timestamp ?? Date.now();
791
+ if (entity === 'track') {
792
+ const eventKey = event;
793
+ if (!this.trackEventBuffer.has(eventKey)) {
794
+ this.trackEventBuffer.set(eventKey, []);
795
+ }
796
+ this.trackEventBuffer.get(eventKey).push({ data, timestamp });
797
+ // Process through streams
798
+ for (const stream of this.streams) {
799
+ if (stream.source.type === 'track' && stream.source.event === event) {
800
+ await stream.processItem(data);
801
+ }
802
+ }
803
+ // Don't return - continue to process joins and coGroups below
804
+ }
805
+ else {
806
+ // Domain events
807
+ const eventKey = `${entity}.${event}`;
808
+ if (!this.eventBuffer.has(eventKey)) {
809
+ this.eventBuffer.set(eventKey, []);
810
+ }
811
+ this.eventBuffer.get(eventKey).push({ data, timestamp });
812
+ // Process through ROOT streams only (child streams get data via parent subscription)
813
+ for (const stream of this.streams) {
814
+ // Check if this stream matches the emit
815
+ const isMatchingSource =
816
+ // Domain events: $.stream.from.Order.created
817
+ ((stream.source.entity === entity || stream.source.entity === '*') &&
818
+ (stream.source.event === event || stream.source.event === '*'));
819
+ if (stream.isRootStream() && isMatchingSource) {
820
+ await stream.processItem(data);
821
+ }
822
+ }
823
+ }
824
+ // NOTE: keyed streams and windowed streams receive data through parent subscriptions
825
+ // They don't need direct processing here anymore
826
+ // Process joins
827
+ for (const join of this.joins) {
828
+ const leftKey = join.left.getKey(data);
829
+ const rightKey = join.right.getKey?.(data);
830
+ // Check if this event matches left stream
831
+ const leftSource = join.left.parentStream?.source;
832
+ const leftSourceMatches = (leftSource?.entity === entity && leftSource?.event === event) ||
833
+ (leftSource?.type === 'track' && entity === 'track' && leftSource?.event === event);
834
+ if (leftSourceMatches) {
835
+ join.leftBuffer.set(leftKey, join.leftBuffer.get(leftKey) ?? []);
836
+ join.leftBuffer.get(leftKey).push({ data, timestamp });
837
+ // Try to match with right buffer
838
+ const rightMatches = join.rightBuffer.get(leftKey) ?? [];
839
+ for (const rightItem of rightMatches) {
840
+ if (Math.abs(timestamp - rightItem.timestamp) <= join.window) {
841
+ const result = join.mapper(data, rightItem.data);
842
+ await join.output.processItem(result);
843
+ }
844
+ }
845
+ }
846
+ // Check if this event matches right stream
847
+ const rightSource = join.right.parentStream?.source;
848
+ const rightSourceMatches = (rightSource?.entity === entity && rightSource?.event === event) ||
849
+ (rightSource?.type === 'track' && entity === 'track' && rightSource?.event === event);
850
+ if (rightSourceMatches) {
851
+ if (rightKey) {
852
+ join.rightBuffer.set(rightKey, join.rightBuffer.get(rightKey) ?? []);
853
+ join.rightBuffer.get(rightKey).push({ data, timestamp });
854
+ // Try to match with left buffer
855
+ const leftMatches = join.leftBuffer.get(rightKey) ?? [];
856
+ for (const leftItem of leftMatches) {
857
+ if (Math.abs(timestamp - leftItem.timestamp) <= join.window) {
858
+ const result = join.mapper(leftItem.data, data);
859
+ await join.output.processItem(result);
860
+ }
861
+ }
862
+ }
863
+ }
864
+ }
865
+ // Process coGroups
866
+ for (const coGroup of this.coGroups) {
867
+ const leftKey = coGroup.left.getKey(data);
868
+ const rightKey = coGroup.right.getKey?.(data);
869
+ const leftSource = coGroup.left.parentStream?.source;
870
+ const leftSourceMatches = (leftSource?.entity === entity && leftSource?.event === event) ||
871
+ (leftSource?.type === 'track' && entity === 'track' && leftSource?.event === event);
872
+ if (leftSourceMatches) {
873
+ coGroup.leftBuffer.set(leftKey, coGroup.leftBuffer.get(leftKey) ?? []);
874
+ coGroup.leftBuffer.get(leftKey).push({ data, timestamp });
875
+ }
876
+ const rightSource = coGroup.right.parentStream?.source;
877
+ const rightSourceMatches = (rightSource?.entity === entity && rightSource?.event === event) ||
878
+ (rightSource?.type === 'track' && entity === 'track' && rightSource?.event === event);
879
+ if (rightSourceMatches) {
880
+ if (rightKey) {
881
+ coGroup.rightBuffer.set(rightKey, coGroup.rightBuffer.get(rightKey) ?? []);
882
+ coGroup.rightBuffer.get(rightKey).push({ data, timestamp });
883
+ }
884
+ }
885
+ }
886
+ },
887
+ get: (name) => this.namedStreams.get(name),
888
+ };
889
+ registerStream(stream) {
890
+ this.streams.push(stream);
891
+ }
892
+ registerKeyedStream(stream) {
893
+ this.keyedStreams.push(stream);
894
+ }
895
+ registerWindowedStream(stream) {
896
+ this.windowedStreams.push(stream);
897
+ }
898
+ registerAggregatedStream(stream) {
899
+ this.aggregatedStreams.push(stream);
900
+ }
901
+ registerSinkStream(stream, type, name) {
902
+ const key = `${type}.${name}`;
903
+ if (!this.sinkStreams.has(key))
904
+ this.sinkStreams.set(key, []);
905
+ this.sinkStreams.get(key).push(stream);
906
+ }
907
+ registerAggregatedSink(stream, type, name) {
908
+ const key = `${type}.${name}`;
909
+ if (!this.aggregatedSinks.has(key))
910
+ this.aggregatedSinks.set(key, []);
911
+ this.aggregatedSinks.get(key).push(stream);
912
+ }
913
+ registerJoin(left, right, window, joinType, mapper, output) {
914
+ this.joins.push({
915
+ left,
916
+ right,
917
+ window,
918
+ joinType,
919
+ mapper,
920
+ output,
921
+ leftBuffer: new Map(),
922
+ rightBuffer: new Map(),
923
+ });
924
+ }
925
+ registerCoGroup(left, right, window, mapper, output) {
926
+ this.coGroups.push({
927
+ left,
928
+ right,
929
+ window,
930
+ mapper,
931
+ output,
932
+ leftBuffer: new Map(),
933
+ rightBuffer: new Map(),
934
+ });
935
+ }
936
+ // Aggregation helpers
937
+ count() {
938
+ return { type: 'count' };
939
+ }
940
+ sum(field) {
941
+ return { type: 'sum', field };
942
+ }
943
+ avg(field) {
944
+ return { type: 'avg', field };
945
+ }
946
+ min(field) {
947
+ return { type: 'min', field };
948
+ }
949
+ max(field) {
950
+ return { type: 'max', field };
951
+ }
952
+ first() {
953
+ return { type: 'first' };
954
+ }
955
+ last() {
956
+ return { type: 'last' };
957
+ }
958
+ collect() {
959
+ return { type: 'collect' };
960
+ }
961
+ distinct(field) {
962
+ return { type: 'distinct', field };
963
+ }
964
+ // Entity proxies
965
+ Customer = this.createEntityProxy('Customer');
966
+ Order = this.createEntityProxy('Order');
967
+ Payment = this.createEntityProxy('Payment');
968
+ createEntityProxy(entityName) {
969
+ return (id) => ({
970
+ get: async () => {
971
+ const storage = this._storage[entityName.toLowerCase() + 's'] ?? this._storage.customers;
972
+ return storage.get(id);
973
+ },
974
+ notify: async (payload) => {
975
+ const handlers = this.entityActionHandlers.get(`${entityName}.notify`) ?? [];
976
+ for (const handler of handlers) {
977
+ handler(id, payload);
978
+ }
979
+ },
980
+ });
981
+ }
982
+ // View namespace
983
+ view = new Proxy({}, {
984
+ get: (_, viewName) => {
985
+ if (!this.viewData.has(viewName)) {
986
+ this.viewData.set(viewName, new Map());
987
+ }
988
+ const viewStore = this.viewData.get(viewName);
989
+ return {
990
+ get: async (key) => viewStore.get(key),
991
+ set: async (key, value) => { viewStore.set(key, value); },
992
+ };
993
+ },
994
+ });
995
+ // Trigger window processing (called when time advances)
996
+ advanceTime(currentTime) {
997
+ for (const windowedStream of this.windowedStreams) {
998
+ // Process aggregations BEFORE triggering window close (which deletes the state)
999
+ const aggregateSpec = windowedStream.getAggregateSpec();
1000
+ const reduceSpec = windowedStream.getReduceSpec();
1001
+ const windowState = windowedStream.getWindowState();
1002
+ if (aggregateSpec || reduceSpec) {
1003
+ for (const [windowKey, state] of windowState.entries()) {
1004
+ const [key, windowId] = windowKey.split('|');
1005
+ let shouldClose = false;
1006
+ let windowInfo;
1007
+ if (windowedStream.window.type === 'tumbling') {
1008
+ const size = windowedStream.window.size;
1009
+ const windowStart = parseInt(windowId);
1010
+ const windowEnd = windowStart + size;
1011
+ windowInfo = { start: windowStart, end: windowEnd };
1012
+ shouldClose = currentTime >= windowEnd;
1013
+ }
1014
+ else if (windowedStream.window.type === 'sliding') {
1015
+ const size = windowedStream.window.size;
1016
+ const slide = windowedStream.window.slide;
1017
+ const windowStart = parseInt(windowId);
1018
+ const windowEnd = windowStart + size;
1019
+ windowInfo = { start: windowStart, end: windowEnd };
1020
+ shouldClose = currentTime >= windowEnd;
1021
+ }
1022
+ else {
1023
+ const gap = windowedStream.window.gap;
1024
+ windowInfo = { start: state.lastTimestamp - gap, end: state.lastTimestamp + gap };
1025
+ shouldClose = currentTime >= state.lastTimestamp + gap;
1026
+ }
1027
+ if (shouldClose) {
1028
+ let result;
1029
+ if (aggregateSpec) {
1030
+ result = this.computeAggregation(aggregateSpec, state.elements, key);
1031
+ }
1032
+ else if (reduceSpec) {
1033
+ result = state.elements.reduce((acc, item) => reduceSpec.reducer(acc, item), reduceSpec.initial);
1034
+ }
1035
+ // Emit to aggregated streams
1036
+ for (const aggStream of this.aggregatedStreams) {
1037
+ if (aggStream.getWindowedStream() === windowedStream) {
1038
+ aggStream.emitResult(result, key, windowInfo);
1039
+ // Handle sinks
1040
+ if (aggStream.sink?.type === 'measure') {
1041
+ const handlers = this.measureHandlers.get(aggStream.sink.metric) ?? [];
1042
+ const value = typeof result === 'object' ? result.revenue ?? result.count ?? 0 : 0;
1043
+ for (const handler of handlers) {
1044
+ handler(value, { region: key });
1045
+ }
1046
+ }
1047
+ if (aggStream.sink?.type === 'view') {
1048
+ const viewName = aggStream.sink.view;
1049
+ if (!this.viewData.has(viewName)) {
1050
+ this.viewData.set(viewName, new Map());
1051
+ }
1052
+ this.viewData.get(viewName).set(key, result);
1053
+ }
1054
+ }
1055
+ }
1056
+ }
1057
+ }
1058
+ }
1059
+ // Trigger window close AFTER processing aggregations (this clears the state)
1060
+ windowedStream.triggerWindowClose(currentTime);
1061
+ }
1062
+ // Process left joins (emit unmatched left elements after window expires)
1063
+ for (const join of this.joins) {
1064
+ if (join.joinType === 'left') {
1065
+ for (const [key, leftItems] of join.leftBuffer.entries()) {
1066
+ const rightItems = join.rightBuffer.get(key) ?? [];
1067
+ for (const leftItem of leftItems) {
1068
+ if (currentTime - leftItem.timestamp > join.window) {
1069
+ // Check if there was a match
1070
+ const hasMatch = rightItems.some((r) => Math.abs(leftItem.timestamp - r.timestamp) <= join.window);
1071
+ if (!hasMatch) {
1072
+ const result = join.mapper(leftItem.data, null);
1073
+ join.output.processItem(result);
1074
+ }
1075
+ }
1076
+ }
1077
+ }
1078
+ }
1079
+ }
1080
+ // Process coGroups
1081
+ for (const coGroup of this.coGroups) {
1082
+ const allKeys = new Set([
1083
+ ...coGroup.leftBuffer.keys(),
1084
+ ...coGroup.rightBuffer.keys(),
1085
+ ]);
1086
+ for (const key of allKeys) {
1087
+ const leftItems = coGroup.leftBuffer.get(key) ?? [];
1088
+ const rightItems = coGroup.rightBuffer.get(key) ?? [];
1089
+ // Check if any items are past the window
1090
+ const expiredLeft = leftItems.filter((i) => currentTime - i.timestamp > coGroup.window);
1091
+ const expiredRight = rightItems.filter((i) => currentTime - i.timestamp > coGroup.window);
1092
+ if (expiredLeft.length > 0 || expiredRight.length > 0) {
1093
+ const result = coGroup.mapper(leftItems.map((i) => i.data), rightItems.map((i) => i.data));
1094
+ coGroup.output.processItem(result);
1095
+ // Clear processed items
1096
+ coGroup.leftBuffer.delete(key);
1097
+ coGroup.rightBuffer.delete(key);
1098
+ }
1099
+ }
1100
+ }
1101
+ }
1102
+ computeAggregation(spec, elements, key) {
1103
+ const result = { key };
1104
+ for (const [name, aggSpec] of Object.entries(spec)) {
1105
+ switch (aggSpec.type) {
1106
+ case 'count':
1107
+ result[name] = elements.length;
1108
+ break;
1109
+ case 'sum':
1110
+ result[name] = elements.reduce((sum, el) => sum + (el[aggSpec.field] ?? 0), 0);
1111
+ break;
1112
+ case 'avg':
1113
+ result[name] =
1114
+ elements.length > 0
1115
+ ? elements.reduce((sum, el) => sum + (el[aggSpec.field] ?? 0), 0) /
1116
+ elements.length
1117
+ : 0;
1118
+ break;
1119
+ case 'min':
1120
+ result[name] = Math.min(...elements.map((el) => el[aggSpec.field] ?? Infinity));
1121
+ break;
1122
+ case 'max':
1123
+ result[name] = Math.max(...elements.map((el) => el[aggSpec.field] ?? -Infinity));
1124
+ break;
1125
+ case 'first':
1126
+ result[name] = elements[0];
1127
+ break;
1128
+ case 'last':
1129
+ result[name] = elements[elements.length - 1];
1130
+ break;
1131
+ case 'collect':
1132
+ result[name] = [...elements];
1133
+ break;
1134
+ case 'distinct':
1135
+ result[name] = new Set(elements.map((el) => el[aggSpec.field])).size;
1136
+ break;
1137
+ }
1138
+ }
1139
+ return result;
1140
+ }
1141
+ }
1142
+ // ============================================================================
1143
+ // Factory
1144
+ // ============================================================================
1145
+ export function createStreamContext() {
1146
+ const ctx = new StreamContextImpl();
1147
+ return ctx;
1148
+ }
1149
+ //# sourceMappingURL=index.js.map