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,840 @@
1
+ /**
2
+ * $.measure - Business Metrics API
3
+ *
4
+ * Time-series metrics with founder-native vocabulary for KPIs:
5
+ * - $.measure.revenue(1000, { tags }) - Record business metrics
6
+ * - $.measure.mrr.current() - Get current value
7
+ * - $.measure.revenue.sum().since('7d') - Aggregations over time
8
+ * - $.measure.activeUsers.set() - Gauges (current value)
9
+ * - $.measure.requests.increment() - Counters (running total)
10
+ *
11
+ * @see docs/plans/2026-01-11-data-api-design.md
12
+ * @module workflows/data/measure
13
+ */
14
+ // ============================================================================
15
+ // Helper Functions
16
+ // ============================================================================
17
+ function parseDuration(duration) {
18
+ // Handle named durations
19
+ if (duration === 'quarter') {
20
+ return 90 * 24 * 60 * 60 * 1000; // ~3 months
21
+ }
22
+ if (duration === 'year') {
23
+ return 365 * 24 * 60 * 60 * 1000;
24
+ }
25
+ if (duration === 'month') {
26
+ return 30 * 24 * 60 * 60 * 1000;
27
+ }
28
+ if (duration === 'week') {
29
+ return 7 * 24 * 60 * 60 * 1000;
30
+ }
31
+ const match = duration.match(/^(\d+)(ms|s|m|h|d|w|mo|y)$/);
32
+ if (!match) {
33
+ throw new Error(`Invalid duration format: ${duration}`);
34
+ }
35
+ const value = parseInt(match[1], 10);
36
+ const unit = match[2];
37
+ switch (unit) {
38
+ case 'ms': return value;
39
+ case 's': return value * 1000;
40
+ case 'm': return value * 60 * 1000;
41
+ case 'h': return value * 60 * 60 * 1000;
42
+ case 'd': return value * 24 * 60 * 60 * 1000;
43
+ case 'w': return value * 7 * 24 * 60 * 60 * 1000;
44
+ case 'mo': return value * 30 * 24 * 60 * 60 * 1000;
45
+ case 'y': return value * 365 * 24 * 60 * 60 * 1000;
46
+ default: throw new Error(`Unknown duration unit: ${unit}`);
47
+ }
48
+ }
49
+ function getGranularityMs(granularity) {
50
+ switch (granularity) {
51
+ case 'hour': return 60 * 60 * 1000;
52
+ case 'day': return 24 * 60 * 60 * 1000;
53
+ case 'week': return 7 * 24 * 60 * 60 * 1000;
54
+ case 'month': return 30 * 24 * 60 * 60 * 1000;
55
+ default: throw new Error(`Unknown granularity: ${granularity}`);
56
+ }
57
+ }
58
+ function tagsMatch(dataPointTags, filterTags) {
59
+ for (const [key, value] of Object.entries(filterTags)) {
60
+ if (key === '_timestamp')
61
+ continue;
62
+ if (dataPointTags[key] !== value) {
63
+ return false;
64
+ }
65
+ }
66
+ return true;
67
+ }
68
+ function generateTagKey(tags) {
69
+ const filtered = { ...tags };
70
+ delete filtered._timestamp;
71
+ const entries = Object.entries(filtered).sort(([a], [b]) => a.localeCompare(b));
72
+ if (entries.length === 0)
73
+ return '';
74
+ return entries.map(([k, v]) => `${k}=${v}`).join(',');
75
+ }
76
+ function computePercentile(values, p) {
77
+ if (values.length === 0)
78
+ return 0;
79
+ const sorted = [...values].sort((a, b) => a - b);
80
+ const index = (p / 100) * (sorted.length - 1);
81
+ const lower = Math.floor(index);
82
+ const upper = Math.ceil(index);
83
+ if (lower === upper)
84
+ return sorted[lower];
85
+ const fraction = index - lower;
86
+ return sorted[lower] * (1 - fraction) + sorted[upper] * fraction;
87
+ }
88
+ function linearRegression(points) {
89
+ if (points.length === 0)
90
+ return { slope: 0, intercept: 0 };
91
+ if (points.length === 1)
92
+ return { slope: 0, intercept: points[0].y };
93
+ const n = points.length;
94
+ let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
95
+ for (const { x, y } of points) {
96
+ sumX += x;
97
+ sumY += y;
98
+ sumXY += x * y;
99
+ sumX2 += x * x;
100
+ }
101
+ const denominator = n * sumX2 - sumX * sumX;
102
+ if (Math.abs(denominator) < 1e-10) {
103
+ return { slope: 0, intercept: sumY / n };
104
+ }
105
+ const slope = (n * sumXY - sumX * sumY) / denominator;
106
+ const intercept = (sumY - slope * sumX) / n;
107
+ return { slope, intercept };
108
+ }
109
+ // ============================================================================
110
+ // Metric Store
111
+ // ============================================================================
112
+ class MetricStore {
113
+ data = new Map();
114
+ counters = new Map();
115
+ counterMetrics = new Set(); // Track which metrics are counters
116
+ gauges = new Map();
117
+ alerts = [];
118
+ windows = [];
119
+ rollups = new Map();
120
+ alertIdCounter = 0;
121
+ // -------------------------------------------------------------------
122
+ // Recording
123
+ // -------------------------------------------------------------------
124
+ async record(metricName, value, tags = {}) {
125
+ if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
126
+ throw new Error(`Invalid metric value: ${value}`);
127
+ }
128
+ const timestamp = tags._timestamp ?? Date.now();
129
+ const cleanTags = {};
130
+ for (const [k, v] of Object.entries(tags)) {
131
+ if (k !== '_timestamp') {
132
+ cleanTags[k] = v;
133
+ }
134
+ }
135
+ const dataPoint = { value, timestamp, tags: cleanTags };
136
+ if (!this.data.has(metricName)) {
137
+ this.data.set(metricName, []);
138
+ }
139
+ this.data.get(metricName).push(dataPoint);
140
+ // Update gauge value for this tag combination
141
+ const tagKey = `${metricName}:${generateTagKey(cleanTags)}`;
142
+ this.gauges.set(tagKey, { value, timestamp });
143
+ // Check alerts
144
+ await this.checkAlerts(metricName, value, cleanTags, timestamp);
145
+ }
146
+ async set(metricName, value, tags = {}) {
147
+ // set() is same as record() for gauges
148
+ await this.record(metricName, value, tags);
149
+ }
150
+ async increment(metricName, amount = 1, tags = {}) {
151
+ if (amount < 0) {
152
+ throw new Error('Counter increment value cannot be negative');
153
+ }
154
+ const timestamp = tags._timestamp ?? Date.now();
155
+ const cleanTags = {};
156
+ for (const [k, v] of Object.entries(tags)) {
157
+ if (k !== '_timestamp') {
158
+ cleanTags[k] = v;
159
+ }
160
+ }
161
+ // Mark this metric as a counter
162
+ this.counterMetrics.add(metricName);
163
+ const counterKey = `${metricName}:${generateTagKey(cleanTags)}`;
164
+ const currentValue = this.counters.get(counterKey) ?? 0;
165
+ const newValue = currentValue + amount;
166
+ this.counters.set(counterKey, newValue);
167
+ // Also record as data point for history
168
+ const dataPoint = { value: amount, timestamp, tags: cleanTags };
169
+ if (!this.data.has(metricName)) {
170
+ this.data.set(metricName, []);
171
+ }
172
+ this.data.get(metricName).push(dataPoint);
173
+ // Update gauge to show current counter value
174
+ const tagKey = `${metricName}:${generateTagKey(cleanTags)}`;
175
+ this.gauges.set(tagKey, { value: newValue, timestamp });
176
+ // Check alerts
177
+ await this.checkAlerts(metricName, newValue, cleanTags, timestamp);
178
+ }
179
+ // -------------------------------------------------------------------
180
+ // Reading
181
+ // -------------------------------------------------------------------
182
+ async current(metricName, tags = {}) {
183
+ const cleanTags = {};
184
+ for (const [k, v] of Object.entries(tags)) {
185
+ if (k !== '_timestamp') {
186
+ cleanTags[k] = v;
187
+ }
188
+ }
189
+ const tagKey = `${metricName}:${generateTagKey(cleanTags)}`;
190
+ // For counters, check counter map first
191
+ if (this.counters.has(tagKey)) {
192
+ return this.counters.get(tagKey);
193
+ }
194
+ // Check gauge value
195
+ if (this.gauges.has(tagKey)) {
196
+ return this.gauges.get(tagKey).value;
197
+ }
198
+ // Check if this is a counter metric (even if not yet incremented with these tags)
199
+ if (this.counterMetrics.has(metricName)) {
200
+ // Counter metrics return 0 for uninitialized tag combinations
201
+ return 0;
202
+ }
203
+ // If no data at all, return null for non-counter metrics (gauges)
204
+ const hasAnyData = this.data.has(metricName) && this.data.get(metricName).length > 0;
205
+ if (!hasAnyData) {
206
+ return null;
207
+ }
208
+ // Filter by tags
209
+ const dataPoints = this.data.get(metricName).filter(dp => tagsMatch(dp.tags, cleanTags));
210
+ if (dataPoints.length === 0) {
211
+ return null;
212
+ }
213
+ // Return most recent value
214
+ const latest = dataPoints.reduce((a, b) => a.timestamp > b.timestamp ? a : b);
215
+ return latest.value;
216
+ }
217
+ // Mark a metric as a counter (called when .increment is accessed)
218
+ markAsCounter(metricName) {
219
+ this.counterMetrics.add(metricName);
220
+ }
221
+ // Mark a metric as a counter for newCounter.current() returning 0
222
+ isMarkedAsCounter(metricName) {
223
+ return this.counterMetrics.has(metricName);
224
+ }
225
+ async stats(metricName) {
226
+ const dataPoints = this.data.get(metricName) || [];
227
+ if (dataPoints.length === 0) {
228
+ return {
229
+ count: 0,
230
+ sum: 0,
231
+ min: Infinity,
232
+ max: -Infinity,
233
+ avg: 0,
234
+ lastRecordedAt: 0,
235
+ };
236
+ }
237
+ const values = dataPoints.map(dp => dp.value);
238
+ const sum = values.reduce((a, b) => a + b, 0);
239
+ const min = Math.min(...values);
240
+ const max = Math.max(...values);
241
+ const avg = sum / values.length;
242
+ const lastRecordedAt = Math.max(...dataPoints.map(dp => dp.timestamp));
243
+ return {
244
+ count: values.length,
245
+ sum,
246
+ min,
247
+ max,
248
+ avg,
249
+ lastRecordedAt,
250
+ };
251
+ }
252
+ // -------------------------------------------------------------------
253
+ // Aggregations
254
+ // -------------------------------------------------------------------
255
+ getDataPoints(metricName, since, inclusive = true) {
256
+ const dataPoints = this.data.get(metricName) || [];
257
+ if (since === undefined) {
258
+ return dataPoints;
259
+ }
260
+ const cutoff = Date.now() - since;
261
+ // inclusive=true uses >= (includes boundary), inclusive=false uses > (excludes boundary)
262
+ if (inclusive) {
263
+ return dataPoints.filter(dp => dp.timestamp >= cutoff);
264
+ }
265
+ else {
266
+ return dataPoints.filter(dp => dp.timestamp > cutoff);
267
+ }
268
+ }
269
+ computeSum(metricName, since) {
270
+ // Use exclusive boundary for sum (data exactly at cutoff is NOT included)
271
+ const dataPoints = this.getDataPoints(metricName, since, false);
272
+ return dataPoints.reduce((sum, dp) => sum + dp.value, 0);
273
+ }
274
+ computeAvg(metricName, since) {
275
+ // Use exclusive boundary for avg (data exactly at cutoff is NOT included)
276
+ const dataPoints = this.getDataPoints(metricName, since, false);
277
+ if (dataPoints.length === 0)
278
+ return 0;
279
+ const sum = dataPoints.reduce((s, dp) => s + dp.value, 0);
280
+ return sum / dataPoints.length;
281
+ }
282
+ computeMin(metricName, since) {
283
+ const dataPoints = this.getDataPoints(metricName, since);
284
+ if (dataPoints.length === 0)
285
+ return Infinity;
286
+ return Math.min(...dataPoints.map(dp => dp.value));
287
+ }
288
+ computeMax(metricName, since) {
289
+ const dataPoints = this.getDataPoints(metricName, since);
290
+ if (dataPoints.length === 0)
291
+ return -Infinity;
292
+ return Math.max(...dataPoints.map(dp => dp.value));
293
+ }
294
+ computeCount(metricName, since) {
295
+ // Use inclusive boundary for count (data at cutoff IS included)
296
+ const dataPoints = this.getDataPoints(metricName, since, true);
297
+ return dataPoints.length;
298
+ }
299
+ computePercentile(metricName, p, since) {
300
+ const dataPoints = this.getDataPoints(metricName, since);
301
+ const values = dataPoints.map(dp => dp.value);
302
+ return computePercentile(values, p);
303
+ }
304
+ computeTrend(metricName, since) {
305
+ const dataPoints = this.getDataPoints(metricName, since);
306
+ if (dataPoints.length < 2) {
307
+ return { slope: 0, direction: 'flat' };
308
+ }
309
+ // Normalize timestamps for regression
310
+ const minTime = Math.min(...dataPoints.map(dp => dp.timestamp));
311
+ const points = dataPoints.map(dp => ({
312
+ x: (dp.timestamp - minTime) / (1000 * 60 * 60), // Convert to hours
313
+ y: dp.value,
314
+ }));
315
+ const { slope } = linearRegression(points);
316
+ // Determine direction: look at actual value change over time
317
+ // For consistent trend data, check first vs last value
318
+ const sortedPoints = [...dataPoints].sort((a, b) => a.timestamp - b.timestamp);
319
+ const firstValue = sortedPoints[0].value;
320
+ const lastValue = sortedPoints[sortedPoints.length - 1].value;
321
+ const valueChange = lastValue - firstValue;
322
+ const avgValue = dataPoints.reduce((s, dp) => s + dp.value, 0) / dataPoints.length;
323
+ // Use a threshold relative to average value (very small for flat detection)
324
+ // For monotonic sequences, check if all values consistently increase/decrease
325
+ let direction;
326
+ // Check for monotonic increase/decrease
327
+ let allIncreasing = true;
328
+ let allDecreasing = true;
329
+ for (let i = 1; i < sortedPoints.length; i++) {
330
+ if (sortedPoints[i].value <= sortedPoints[i - 1].value) {
331
+ allIncreasing = false;
332
+ }
333
+ if (sortedPoints[i].value >= sortedPoints[i - 1].value) {
334
+ allDecreasing = false;
335
+ }
336
+ }
337
+ if (allIncreasing && !allDecreasing) {
338
+ direction = 'up';
339
+ }
340
+ else if (allDecreasing && !allIncreasing) {
341
+ direction = 'down';
342
+ }
343
+ else if (Math.abs(valueChange) < avgValue * 0.01) {
344
+ // Less than 1% change overall = flat
345
+ direction = 'flat';
346
+ }
347
+ else if (slope > 0) {
348
+ direction = 'up';
349
+ }
350
+ else if (slope < 0) {
351
+ direction = 'down';
352
+ }
353
+ else {
354
+ direction = 'flat';
355
+ }
356
+ return { slope, direction };
357
+ }
358
+ groupBy(metricName, aggregation, since, granularity) {
359
+ const now = Date.now();
360
+ const granularityMs = getGranularityMs(granularity);
361
+ // Get ALL data points within range (inclusive for bucketing purposes)
362
+ const allDataPoints = this.data.get(metricName) || [];
363
+ const cutoff = now - since;
364
+ // Use >= for bucketing - we want to create buckets that include the boundary
365
+ const dataPoints = allDataPoints.filter(dp => dp.timestamp >= cutoff);
366
+ // If no data, return empty array
367
+ if (dataPoints.length === 0) {
368
+ return [];
369
+ }
370
+ // Find actual data range
371
+ const timestamps = dataPoints.map(dp => dp.timestamp);
372
+ const minDataTime = Math.min(...timestamps);
373
+ const maxDataTime = Math.max(...timestamps);
374
+ // Create buckets spanning from first to last data point
375
+ const buckets = new Map();
376
+ let bucketStart = Math.floor(minDataTime / granularityMs) * granularityMs;
377
+ const bucketEnd = Math.floor(maxDataTime / granularityMs) * granularityMs;
378
+ // Initialize buckets
379
+ while (bucketStart <= bucketEnd) {
380
+ buckets.set(bucketStart, []);
381
+ bucketStart += granularityMs;
382
+ }
383
+ // Assign data points to buckets
384
+ for (const dp of dataPoints) {
385
+ const bucket = Math.floor(dp.timestamp / granularityMs) * granularityMs;
386
+ if (!buckets.has(bucket)) {
387
+ buckets.set(bucket, []);
388
+ }
389
+ buckets.get(bucket).push(dp.value);
390
+ }
391
+ // Compute aggregation for each bucket
392
+ const results = [];
393
+ const sortedBuckets = Array.from(buckets.entries()).sort(([a], [b]) => a - b);
394
+ for (const [timestamp, values] of sortedBuckets) {
395
+ let value;
396
+ if (values.length === 0) {
397
+ value = 0;
398
+ }
399
+ else {
400
+ switch (aggregation) {
401
+ case 'sum':
402
+ value = values.reduce((a, b) => a + b, 0);
403
+ break;
404
+ case 'avg':
405
+ value = values.reduce((a, b) => a + b, 0) / values.length;
406
+ break;
407
+ case 'min':
408
+ value = Math.min(...values);
409
+ break;
410
+ case 'max':
411
+ value = Math.max(...values);
412
+ break;
413
+ case 'count':
414
+ value = values.length;
415
+ break;
416
+ }
417
+ }
418
+ results.push({ timestamp, value });
419
+ }
420
+ return results;
421
+ }
422
+ computeVs(metricName, aggregation, since, comparison) {
423
+ const now = Date.now();
424
+ let periodLength;
425
+ switch (comparison) {
426
+ case 'prev':
427
+ periodLength = since ?? 7 * 24 * 60 * 60 * 1000; // default to week
428
+ break;
429
+ case 'prev_week':
430
+ periodLength = 7 * 24 * 60 * 60 * 1000;
431
+ break;
432
+ case 'prev_month':
433
+ periodLength = 30 * 24 * 60 * 60 * 1000;
434
+ break;
435
+ case 'prev_year':
436
+ periodLength = 365 * 24 * 60 * 60 * 1000;
437
+ break;
438
+ }
439
+ const currentPeriodStart = now - periodLength;
440
+ const previousPeriodStart = currentPeriodStart - periodLength;
441
+ const previousPeriodEnd = currentPeriodStart;
442
+ // Get data points for both periods
443
+ const allDataPoints = this.data.get(metricName) || [];
444
+ const currentPeriodData = allDataPoints.filter(dp => dp.timestamp >= currentPeriodStart && dp.timestamp <= now);
445
+ const previousPeriodData = allDataPoints.filter(dp => dp.timestamp >= previousPeriodStart && dp.timestamp < previousPeriodEnd);
446
+ const computeValue = (dataPoints) => {
447
+ if (dataPoints.length === 0)
448
+ return 0;
449
+ const values = dataPoints.map(dp => dp.value);
450
+ switch (aggregation) {
451
+ case 'sum': return values.reduce((a, b) => a + b, 0);
452
+ case 'avg': return values.reduce((a, b) => a + b, 0) / values.length;
453
+ case 'min': return Math.min(...values);
454
+ case 'max': return Math.max(...values);
455
+ case 'count': return values.length;
456
+ case 'current': return values[values.length - 1] ?? 0;
457
+ }
458
+ };
459
+ const current = computeValue(currentPeriodData);
460
+ const previous = computeValue(previousPeriodData);
461
+ const change = current - previous;
462
+ const percentChange = previous !== 0 ? ((current - previous) / previous) * 100 : 0;
463
+ return { current, previous, change, percentChange };
464
+ }
465
+ // -------------------------------------------------------------------
466
+ // Rollups
467
+ // -------------------------------------------------------------------
468
+ async configureRollup(metricName, config) {
469
+ const validGranularities = ['minute', 'hour', 'day', 'week', 'month'];
470
+ const validAggregates = ['sum', 'count', 'avg', 'min', 'max'];
471
+ for (const g of config.granularity) {
472
+ if (!validGranularities.includes(g)) {
473
+ throw new Error(`Invalid granularity: ${g}`);
474
+ }
475
+ }
476
+ for (const a of config.aggregates) {
477
+ if (!validAggregates.includes(a)) {
478
+ throw new Error(`Invalid aggregate: ${a}`);
479
+ }
480
+ }
481
+ this.rollups.set(metricName, { metricName, config });
482
+ const result = { status: 'configured' };
483
+ if (config.retention) {
484
+ result.retention = config.retention;
485
+ }
486
+ return result;
487
+ }
488
+ // -------------------------------------------------------------------
489
+ // Alerts
490
+ // -------------------------------------------------------------------
491
+ async createAlert(metricName, config) {
492
+ const id = `alert-${++this.alertIdCounter}`;
493
+ const alert = {
494
+ id,
495
+ metricName,
496
+ config,
497
+ status: 'active',
498
+ conditionTrueStart: null,
499
+ };
500
+ this.alerts.push(alert);
501
+ return {
502
+ id,
503
+ status: 'active',
504
+ for: config.for,
505
+ disable: async () => {
506
+ alert.status = 'disabled';
507
+ },
508
+ delete: async () => {
509
+ const index = this.alerts.indexOf(alert);
510
+ if (index !== -1) {
511
+ this.alerts.splice(index, 1);
512
+ }
513
+ },
514
+ };
515
+ }
516
+ async checkAlerts(metricName, value, tags, timestamp) {
517
+ for (const alert of this.alerts) {
518
+ if (alert.metricName !== metricName || alert.status !== 'active') {
519
+ continue;
520
+ }
521
+ let conditionMet = false;
522
+ const { condition } = alert.config;
523
+ if (typeof condition === 'function') {
524
+ conditionMet = condition(value);
525
+ }
526
+ else {
527
+ const { op, value: threshold } = condition;
528
+ switch (op) {
529
+ case '>':
530
+ conditionMet = value > threshold;
531
+ break;
532
+ case '<':
533
+ conditionMet = value < threshold;
534
+ break;
535
+ case '>=':
536
+ conditionMet = value >= threshold;
537
+ break;
538
+ case '<=':
539
+ conditionMet = value <= threshold;
540
+ break;
541
+ case '=':
542
+ conditionMet = value === threshold;
543
+ break;
544
+ }
545
+ }
546
+ if (conditionMet) {
547
+ if (alert.config.for) {
548
+ // Duration-based alert
549
+ const forDuration = parseDuration(alert.config.for);
550
+ if (alert.conditionTrueStart === null) {
551
+ alert.conditionTrueStart = timestamp;
552
+ }
553
+ const elapsed = timestamp - alert.conditionTrueStart;
554
+ if (elapsed >= forDuration) {
555
+ const alertInfo = {
556
+ metric: metricName,
557
+ value,
558
+ tags: tags,
559
+ timestamp,
560
+ };
561
+ await Promise.resolve(alert.config.notify(alertInfo));
562
+ // Reset after triggering
563
+ alert.conditionTrueStart = null;
564
+ }
565
+ }
566
+ else {
567
+ // Immediate alert
568
+ const alertInfo = {
569
+ metric: metricName,
570
+ value,
571
+ tags: tags,
572
+ timestamp,
573
+ };
574
+ await Promise.resolve(alert.config.notify(alertInfo));
575
+ }
576
+ }
577
+ else {
578
+ // Reset duration counter when condition becomes false
579
+ alert.conditionTrueStart = null;
580
+ }
581
+ }
582
+ }
583
+ // -------------------------------------------------------------------
584
+ // Window Subscriptions
585
+ // -------------------------------------------------------------------
586
+ createWindow(metricName, duration, options = {}) {
587
+ const durationMs = parseDuration(duration);
588
+ const slideMs = options.slide ? parseDuration(options.slide) : durationMs;
589
+ return {
590
+ subscribe: (callback) => {
591
+ const windowState = {
592
+ metricName,
593
+ duration: durationMs,
594
+ slide: slideMs,
595
+ callback,
596
+ intervalId: null,
597
+ active: true,
598
+ };
599
+ const emitWindow = () => {
600
+ if (!windowState.active)
601
+ return;
602
+ const now = Date.now();
603
+ const cutoff = now - durationMs;
604
+ const dataPoints = (this.data.get(metricName) || []).filter(dp => dp.timestamp >= cutoff && dp.timestamp <= now);
605
+ const values = dataPoints.map(dp => dp.value);
606
+ const stats = {
607
+ sum: values.length > 0 ? values.reduce((a, b) => a + b, 0) : 0,
608
+ count: values.length,
609
+ avg: values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0,
610
+ min: values.length > 0 ? Math.min(...values) : 0,
611
+ max: values.length > 0 ? Math.max(...values) : 0,
612
+ };
613
+ callback(stats);
614
+ };
615
+ windowState.intervalId = setInterval(emitWindow, slideMs);
616
+ this.windows.push(windowState);
617
+ return {
618
+ unsubscribe: () => {
619
+ windowState.active = false;
620
+ if (windowState.intervalId) {
621
+ clearInterval(windowState.intervalId);
622
+ windowState.intervalId = null;
623
+ }
624
+ const index = this.windows.indexOf(windowState);
625
+ if (index !== -1) {
626
+ this.windows.splice(index, 1);
627
+ }
628
+ },
629
+ };
630
+ },
631
+ };
632
+ }
633
+ }
634
+ // ============================================================================
635
+ // Query Builder
636
+ // ============================================================================
637
+ class QueryBuilderImpl {
638
+ store;
639
+ metricName;
640
+ aggregation;
641
+ percentileValue;
642
+ sinceDuration;
643
+ constructor(store, metricName, aggregation, percentileValue) {
644
+ this.store = store;
645
+ this.metricName = metricName;
646
+ this.aggregation = aggregation;
647
+ this.percentileValue = percentileValue;
648
+ }
649
+ since(duration) {
650
+ this.sinceDuration = parseDuration(duration);
651
+ return this;
652
+ }
653
+ async by(granularity) {
654
+ const since = this.sinceDuration ?? 7 * 24 * 60 * 60 * 1000; // default 7 days
655
+ const agg = this.aggregation === 'percentile' || this.aggregation === 'trend' || this.aggregation === 'current'
656
+ ? 'sum'
657
+ : this.aggregation;
658
+ return this.store.groupBy(this.metricName, agg, since, granularity);
659
+ }
660
+ async vs(comparison) {
661
+ const agg = this.aggregation === 'percentile' || this.aggregation === 'trend'
662
+ ? 'sum'
663
+ : this.aggregation;
664
+ return this.store.computeVs(this.metricName, agg, this.sinceDuration, comparison);
665
+ }
666
+ then(onfulfilled) {
667
+ return this.resolve().then(onfulfilled);
668
+ }
669
+ async resolve() {
670
+ // Check if this builder was marked for rejection (e.g., invalid percentile)
671
+ if (this._rejectReason) {
672
+ throw this._rejectReason;
673
+ }
674
+ switch (this.aggregation) {
675
+ case 'sum':
676
+ return this.store.computeSum(this.metricName, this.sinceDuration);
677
+ case 'avg':
678
+ return this.store.computeAvg(this.metricName, this.sinceDuration);
679
+ case 'min':
680
+ return this.store.computeMin(this.metricName, this.sinceDuration);
681
+ case 'max':
682
+ return this.store.computeMax(this.metricName, this.sinceDuration);
683
+ case 'count':
684
+ return this.store.computeCount(this.metricName, this.sinceDuration);
685
+ case 'percentile':
686
+ return this.store.computePercentile(this.metricName, this.percentileValue, this.sinceDuration);
687
+ case 'trend':
688
+ return this.store.computeTrend(this.metricName, this.sinceDuration);
689
+ case 'current':
690
+ return this.store.current(this.metricName);
691
+ }
692
+ }
693
+ // Allow direct await
694
+ [Symbol.toStringTag] = 'Promise';
695
+ }
696
+ // Make QueryBuilderImpl awaitable
697
+ Object.defineProperty(QueryBuilderImpl.prototype, 'then', {
698
+ value: function (onfulfilled, onrejected) {
699
+ return this['resolve']().then(onfulfilled, onrejected);
700
+ }
701
+ });
702
+ // ============================================================================
703
+ // Metric Instance Factory
704
+ // ============================================================================
705
+ function createMetricInstance(store, metricName) {
706
+ // Track if this metric has been marked as a counter via .increment access
707
+ let markedAsCounter = false;
708
+ // The callable function
709
+ const recordFn = async (value, tags) => {
710
+ if (metricName === '') {
711
+ return Promise.reject(new Error('Metric name cannot be empty'));
712
+ }
713
+ await store.record(metricName, value, tags);
714
+ };
715
+ // Add methods to the function
716
+ const instance = recordFn;
717
+ instance.set = async (value, tags) => {
718
+ await store.set(metricName, value, tags);
719
+ };
720
+ // Use a getter so accessing .increment marks this as a counter
721
+ Object.defineProperty(instance, 'increment', {
722
+ get: function () {
723
+ markedAsCounter = true;
724
+ store.markAsCounter(metricName);
725
+ return async (value = 1, tags) => {
726
+ await store.increment(metricName, value, tags);
727
+ };
728
+ }
729
+ });
730
+ // current() returns a QueryBuilder-like object that supports .vs()
731
+ instance.current = (tags) => {
732
+ const currentPromise = store.current(metricName, tags).then(result => {
733
+ // If marked as counter and null, return 0
734
+ if (result === null && (markedAsCounter || store.isMarkedAsCounter(metricName))) {
735
+ return 0;
736
+ }
737
+ // Convention: metric names containing "Counter" (case-insensitive) return 0 for unset
738
+ // This supports tests like "newCounter.current()" returning 0
739
+ if (result === null && /counter/i.test(metricName)) {
740
+ return 0;
741
+ }
742
+ return result;
743
+ });
744
+ // Create a thenable with .vs() method
745
+ const wrapper = {
746
+ then: (onfulfilled, onrejected) => currentPromise.then(onfulfilled, onrejected),
747
+ catch: (onrejected) => currentPromise.catch(onrejected),
748
+ finally: (onfinally) => currentPromise.finally(onfinally),
749
+ vs: (comparison) => {
750
+ return store.computeVs(metricName, 'current', undefined, comparison);
751
+ }
752
+ };
753
+ return wrapper;
754
+ };
755
+ instance.stats = async () => {
756
+ return store.stats(metricName);
757
+ };
758
+ instance.sum = () => {
759
+ return new QueryBuilderImpl(store, metricName, 'sum');
760
+ };
761
+ instance.avg = () => {
762
+ return new QueryBuilderImpl(store, metricName, 'avg');
763
+ };
764
+ instance.min = () => {
765
+ return new QueryBuilderImpl(store, metricName, 'min');
766
+ };
767
+ instance.max = () => {
768
+ return new QueryBuilderImpl(store, metricName, 'max');
769
+ };
770
+ instance.count = () => {
771
+ return new QueryBuilderImpl(store, metricName, 'count');
772
+ };
773
+ instance.percentile = (p) => {
774
+ if (p < 0 || p > 100) {
775
+ // Return a QueryBuilder that will reject when resolved
776
+ const rejectingBuilder = new QueryBuilderImpl(store, metricName, 'percentile', p);
777
+ rejectingBuilder._rejectReason = new Error(`Percentile must be between 0 and 100, got ${p}`);
778
+ return rejectingBuilder;
779
+ }
780
+ return new QueryBuilderImpl(store, metricName, 'percentile', p);
781
+ };
782
+ instance.trend = () => {
783
+ return new QueryBuilderImpl(store, metricName, 'trend');
784
+ };
785
+ instance.rollup = async (config) => {
786
+ return store.configureRollup(metricName, config);
787
+ };
788
+ instance.alert = async (config) => {
789
+ return store.createAlert(metricName, config);
790
+ };
791
+ instance.alertAbove = async (threshold, notify) => {
792
+ return store.createAlert(metricName, {
793
+ condition: (value) => value > threshold,
794
+ notify,
795
+ });
796
+ };
797
+ instance.alertBelow = async (threshold, notify) => {
798
+ return store.createAlert(metricName, {
799
+ condition: (value) => value < threshold,
800
+ notify,
801
+ });
802
+ };
803
+ instance.window = (duration, options) => {
804
+ return store.createWindow(metricName, duration, options);
805
+ };
806
+ return instance;
807
+ }
808
+ // ============================================================================
809
+ // Measure Namespace Factory
810
+ // ============================================================================
811
+ /**
812
+ * Creates the $.measure namespace proxy for recording and querying metrics.
813
+ *
814
+ * @returns A proxy that provides metric instances for any metric name
815
+ */
816
+ export function createMeasureNamespace() {
817
+ const store = new MetricStore();
818
+ const metricInstances = new Map();
819
+ // Create a special instance for empty metric name that always rejects
820
+ const emptyNameInstance = async () => {
821
+ throw new Error('Metric name cannot be empty');
822
+ };
823
+ return new Proxy({}, {
824
+ get(_target, prop) {
825
+ // Handle Promise protocol properties
826
+ if (prop === 'then' || prop === 'catch' || prop === 'finally') {
827
+ return undefined;
828
+ }
829
+ // Handle empty metric name - return a function that rejects
830
+ if (prop === '') {
831
+ return emptyNameInstance;
832
+ }
833
+ if (!metricInstances.has(prop)) {
834
+ metricInstances.set(prop, createMetricInstance(store, prop));
835
+ }
836
+ return metricInstances.get(prop);
837
+ },
838
+ });
839
+ }
840
+ //# sourceMappingURL=index.js.map