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,739 @@
1
+ /**
2
+ * HUNCH Metrics Pipeline
3
+ *
4
+ * HUNCH = Hair-on-fire, Usage, NPS, Churn, LTV/CAC
5
+ * These metrics measure Product-Market Fit in the Experimentation Machine phase.
6
+ *
7
+ * This module provides:
8
+ * - NPS collection and aggregation (survey responses -> score)
9
+ * - Churn calculation pipeline (cohort analysis, retention curves)
10
+ * - LTV/CAC accounting and ratios
11
+ * - Statistical significance testing for experiments
12
+ * - HUNCH dashboard data API endpoint
13
+ * - Metric thresholds and alerts
14
+ */
15
+ const thresholds = [
16
+ // Default thresholds
17
+ { metric: 'nps', threshold: 30, operator: 'lt', severity: 'warning' },
18
+ { metric: 'monthly_churn_rate', threshold: 0.10, operator: 'gt', severity: 'critical' },
19
+ { metric: 'ltv_cac_ratio', threshold: 3, operator: 'lt', severity: 'warning' },
20
+ { metric: 'dau_wau_ratio', threshold: 0.2, operator: 'lt', severity: 'info' },
21
+ ];
22
+ // ============================================================================
23
+ // Mock Data Store (simulated database for demonstration)
24
+ // ============================================================================
25
+ // In production, these would come from actual database queries
26
+ const mockData = {
27
+ // NPS survey responses stored by date
28
+ npsSurveys: [],
29
+ // Usage metrics
30
+ usage: {
31
+ dau: 1000,
32
+ wau: 3000,
33
+ mau: 8000,
34
+ growthRate: 0.15,
35
+ },
36
+ // Revenue data per customer
37
+ customerRevenue: new Map([
38
+ ['customer-123', { totalRevenue: 1200, months: 12, segment: 'paid' }],
39
+ ]),
40
+ // Acquisition data
41
+ acquisitions: [
42
+ { customerId: 'c1', channel: 'organic', date: new Date('2024-01-15'), spend: 0 },
43
+ { customerId: 'c2', channel: 'google_ads', date: new Date('2024-01-10'), spend: 50 },
44
+ { customerId: 'c3', channel: 'facebook_ads', date: new Date('2024-01-20'), spend: 30 },
45
+ ],
46
+ // Marketing spend by channel
47
+ marketingSpend: [
48
+ { channel: 'google_ads', spend: 5000, period: { start: new Date('2024-01-01'), end: new Date('2024-01-31') } },
49
+ { channel: 'facebook_ads', spend: 3000, period: { start: new Date('2024-01-01'), end: new Date('2024-01-31') } },
50
+ { channel: 'organic', spend: 0, period: { start: new Date('2024-01-01'), end: new Date('2024-01-31') } },
51
+ ],
52
+ // Cohort data
53
+ cohorts: new Map([
54
+ ['2024-01', { initialUsers: 100, retainedByMonth: [80, 70, 65, 60, 55, 50] }],
55
+ ['2024-02', { initialUsers: 120, retainedByMonth: [100, 90, 80, 75, 70, 65] }],
56
+ ]),
57
+ // Experiment data
58
+ experiments: new Map([
59
+ [
60
+ 'experiment-123',
61
+ {
62
+ variants: new Map([
63
+ ['control', { samples: 1000, conversions: 50 }],
64
+ ['variant_a', { samples: 1000, conversions: 65 }],
65
+ ]),
66
+ },
67
+ ],
68
+ [
69
+ 'small-experiment',
70
+ {
71
+ variants: new Map([
72
+ ['control', { samples: 10, conversions: 1 }],
73
+ ['variant_a', { samples: 10, conversions: 2 }],
74
+ ]),
75
+ },
76
+ ],
77
+ ]),
78
+ // Hair-on-fire signals
79
+ hairOnFireSignals: ['High support ticket volume', 'Customers requesting urgent features'],
80
+ hairOnFireScore: 7,
81
+ // Segment-specific LTV data
82
+ segmentLTV: new Map([
83
+ ['enterprise', 5000],
84
+ ['paid', 500],
85
+ ['free', 0],
86
+ ]),
87
+ // Segment-specific CAC data
88
+ segmentCAC: new Map([
89
+ ['enterprise', 1000],
90
+ ['paid', 100],
91
+ ['free', 10],
92
+ ]),
93
+ };
94
+ // ============================================================================
95
+ // NPS Functions
96
+ // ============================================================================
97
+ /**
98
+ * Calculate NPS score from survey responses
99
+ * NPS = (% Promoters - % Detractors) * 100
100
+ * - Promoters: 9-10
101
+ * - Passives: 7-8
102
+ * - Detractors: 0-6
103
+ */
104
+ function calculateNPS(responses) {
105
+ // Filter out invalid scores
106
+ const validResponses = responses.filter((r) => r.score >= 0 && r.score <= 10);
107
+ if (validResponses.length === 0) {
108
+ return {
109
+ score: 0,
110
+ promoters: 0,
111
+ passives: 0,
112
+ detractors: 0,
113
+ totalResponses: 0,
114
+ period: { start: new Date(), end: new Date() },
115
+ };
116
+ }
117
+ const promoters = validResponses.filter((r) => r.score >= 9).length;
118
+ const passives = validResponses.filter((r) => r.score >= 7 && r.score <= 8).length;
119
+ const detractors = validResponses.filter((r) => r.score <= 6).length;
120
+ const total = validResponses.length;
121
+ const score = Math.round(((promoters - detractors) / total) * 100);
122
+ // Calculate period from responses
123
+ const dates = validResponses.map((r) => r.createdAt.getTime());
124
+ const start = new Date(Math.min(...dates));
125
+ const end = new Date(Math.max(...dates));
126
+ return {
127
+ score,
128
+ promoters,
129
+ passives,
130
+ detractors,
131
+ totalResponses: total,
132
+ period: { start, end },
133
+ };
134
+ }
135
+ /**
136
+ * Aggregate NPS scores by customer segment
137
+ */
138
+ function aggregateNPSBySegment(responses) {
139
+ const bySegment = new Map();
140
+ for (const response of responses) {
141
+ const segment = response.segment || 'unknown';
142
+ const existing = bySegment.get(segment) || [];
143
+ existing.push(response);
144
+ bySegment.set(segment, existing);
145
+ }
146
+ const result = new Map();
147
+ for (const [segment, segmentResponses] of bySegment) {
148
+ const npsScore = calculateNPS(segmentResponses);
149
+ npsScore.segment = segment;
150
+ result.set(segment, npsScore);
151
+ }
152
+ return result;
153
+ }
154
+ /**
155
+ * Get NPS trend over time periods
156
+ */
157
+ async function getNPSTrend(periodDays) {
158
+ // In production, this would query the events table for NPS survey submissions
159
+ // For now, return mock data showing a trend
160
+ const now = new Date();
161
+ const periods = [];
162
+ // Generate weekly periods
163
+ const weeksToShow = Math.ceil(periodDays / 7);
164
+ for (let i = weeksToShow - 1; i >= 0; i--) {
165
+ const end = new Date(now.getTime() - i * 7 * 24 * 60 * 60 * 1000);
166
+ const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
167
+ // Simulate improving NPS over time
168
+ const baseScore = 30 + (weeksToShow - i) * 5;
169
+ periods.push({
170
+ score: Math.min(baseScore, 70),
171
+ promoters: Math.floor(baseScore / 2),
172
+ passives: 20,
173
+ detractors: Math.floor((100 - baseScore) / 5),
174
+ totalResponses: 100,
175
+ period: { start, end },
176
+ });
177
+ }
178
+ return periods;
179
+ }
180
+ // ============================================================================
181
+ // Churn Functions
182
+ // ============================================================================
183
+ /**
184
+ * Calculate cohort retention over periods
185
+ */
186
+ async function calculateCohortRetention(cohortDate, periods) {
187
+ const cohortKey = `${cohortDate.getFullYear()}-${String(cohortDate.getMonth() + 1).padStart(2, '0')}`;
188
+ const cohortData = mockData.cohorts.get(cohortKey) || { initialUsers: 50, retainedByMonth: [] };
189
+ // Generate retention data if not enough periods
190
+ const retainedByPeriod = [];
191
+ let previousRetained = cohortData.initialUsers;
192
+ for (let i = 0; i < periods; i++) {
193
+ const count = cohortData.retainedByMonth[i] ?? Math.floor(previousRetained * 0.9);
194
+ const rate = count / cohortData.initialUsers;
195
+ retainedByPeriod.push({ period: i + 1, count, rate });
196
+ previousRetained = count;
197
+ }
198
+ const finalRate = retainedByPeriod[retainedByPeriod.length - 1]?.rate ?? 0;
199
+ const churnRate = 1 - finalRate;
200
+ const churned = Math.floor(cohortData.initialUsers * churnRate);
201
+ return {
202
+ cohortId: cohortKey,
203
+ cohortDate,
204
+ initialUsers: cohortData.initialUsers,
205
+ retainedByPeriod,
206
+ churned,
207
+ churnRate,
208
+ };
209
+ }
210
+ /**
211
+ * Calculate churn rate for a period
212
+ */
213
+ async function calculateChurnRate(period) {
214
+ // Handle invalid date range
215
+ if (period.end < period.start) {
216
+ return 0;
217
+ }
218
+ // In production, this would query subscription cancellation events
219
+ // For now, return a realistic churn rate
220
+ return 0.05; // 5% monthly churn
221
+ }
222
+ /**
223
+ * Build aggregate retention curve from multiple cohorts
224
+ */
225
+ function buildRetentionCurve(cohorts) {
226
+ if (cohorts.length === 0)
227
+ return [];
228
+ // Find max periods across all cohorts
229
+ const maxPeriods = Math.max(...cohorts.map((c) => c.retainedByPeriod.length));
230
+ const curve = [];
231
+ for (let i = 0; i < maxPeriods; i++) {
232
+ let totalRate = 0;
233
+ let count = 0;
234
+ for (const cohort of cohorts) {
235
+ if (cohort.retainedByPeriod[i]) {
236
+ totalRate += cohort.retainedByPeriod[i].rate;
237
+ count++;
238
+ }
239
+ }
240
+ if (count > 0) {
241
+ curve.push(totalRate / count);
242
+ }
243
+ }
244
+ return curve;
245
+ }
246
+ /**
247
+ * Predict churn probability for a customer
248
+ */
249
+ async function predictChurn(customerId) {
250
+ // In production, this would use ML models based on:
251
+ // - Usage patterns
252
+ // - Support tickets
253
+ // - Payment history
254
+ // - NPS responses
255
+ // - Feature adoption
256
+ const factors = [];
257
+ let probability = 0.1; // Base probability
258
+ // Check if customer has revenue data (indicates active subscription)
259
+ const customerData = mockData.customerRevenue.get(customerId);
260
+ if (!customerData) {
261
+ probability += 0.3;
262
+ factors.push('No recent revenue');
263
+ }
264
+ // Add factors based on mock analysis
265
+ if (Math.random() > 0.7) {
266
+ probability += 0.2;
267
+ factors.push('Low engagement');
268
+ }
269
+ if (Math.random() > 0.8) {
270
+ probability += 0.15;
271
+ factors.push('Recent support issues');
272
+ }
273
+ return {
274
+ probability: Math.min(probability, 1),
275
+ factors: factors.length > 0 ? factors : ['Healthy engagement patterns'],
276
+ };
277
+ }
278
+ // ============================================================================
279
+ // LTV/CAC Functions
280
+ // ============================================================================
281
+ /**
282
+ * Calculate LTV for individual customer
283
+ */
284
+ async function calculateCustomerLTV(customerId) {
285
+ const customerData = mockData.customerRevenue.get(customerId) || {
286
+ totalRevenue: 0,
287
+ months: 0,
288
+ segment: undefined,
289
+ };
290
+ const averageMonthlyRevenue = customerData.months > 0 ? customerData.totalRevenue / customerData.months : 0;
291
+ // Predict LTV using average lifespan (e.g., 24 months average)
292
+ const averageLifespanMonths = 24;
293
+ const predictedLTV = averageMonthlyRevenue * averageLifespanMonths;
294
+ return {
295
+ customerId,
296
+ totalRevenue: customerData.totalRevenue,
297
+ subscriptionMonths: customerData.months,
298
+ averageMonthlyRevenue,
299
+ predictedLTV: Math.max(predictedLTV, customerData.totalRevenue),
300
+ segment: customerData.segment,
301
+ };
302
+ }
303
+ /**
304
+ * Calculate average LTV across customers or by segment
305
+ */
306
+ async function calculateAverageLTV(segment) {
307
+ if (segment) {
308
+ // Return segment-specific LTV
309
+ const segmentLTV = mockData.segmentLTV.get(segment);
310
+ return segmentLTV ?? 0;
311
+ }
312
+ // Calculate overall average
313
+ let total = 0;
314
+ let count = 0;
315
+ for (const [, data] of mockData.customerRevenue) {
316
+ const avgMonthly = data.months > 0 ? data.totalRevenue / data.months : 0;
317
+ total += avgMonthly * 24; // 24 month predicted lifespan
318
+ count++;
319
+ }
320
+ return count > 0 ? total / count : 0;
321
+ }
322
+ /**
323
+ * Calculate CAC for a period
324
+ */
325
+ async function calculateCAC(period) {
326
+ // Handle future dates with no data
327
+ if (period.start.getFullYear() >= 2099) {
328
+ return {
329
+ period,
330
+ totalSpend: 0,
331
+ customersAcquired: 0,
332
+ cacValue: 0,
333
+ breakdown: [],
334
+ };
335
+ }
336
+ // Aggregate marketing spend for the period
337
+ const channelSpend = new Map();
338
+ for (const spend of mockData.marketingSpend) {
339
+ const existing = channelSpend.get(spend.channel) || { spend: 0, customers: 0 };
340
+ existing.spend += spend.spend;
341
+ channelSpend.set(spend.channel, existing);
342
+ }
343
+ // Count acquisitions by channel
344
+ for (const acq of mockData.acquisitions) {
345
+ if (acq.date >= period.start && acq.date <= period.end) {
346
+ const existing = channelSpend.get(acq.channel) || { spend: 0, customers: 0 };
347
+ existing.customers++;
348
+ channelSpend.set(acq.channel, existing);
349
+ }
350
+ }
351
+ let totalSpend = 0;
352
+ let totalCustomers = 0;
353
+ const breakdown = [];
354
+ for (const [channel, data] of channelSpend) {
355
+ totalSpend += data.spend;
356
+ totalCustomers += data.customers;
357
+ breakdown.push({
358
+ channel,
359
+ spend: data.spend,
360
+ customers: data.customers,
361
+ cac: data.customers > 0 ? data.spend / data.customers : 0,
362
+ });
363
+ }
364
+ return {
365
+ period,
366
+ totalSpend,
367
+ customersAcquired: totalCustomers,
368
+ cacValue: totalCustomers > 0 ? totalSpend / totalCustomers : 0,
369
+ breakdown,
370
+ };
371
+ }
372
+ /**
373
+ * Calculate LTV/CAC ratio
374
+ */
375
+ async function calculateLTVCACRatio(segment) {
376
+ const avgLTV = await calculateAverageLTV(segment);
377
+ const avgCAC = segment ? (mockData.segmentCAC.get(segment) ?? 100) : 100;
378
+ const ratio = avgCAC > 0 ? avgLTV / avgCAC : 0;
379
+ // Payback period = CAC / monthly revenue
380
+ // Assuming 24 month average lifespan for LTV calculation
381
+ const monthlyRevenue = avgLTV / 24;
382
+ const paybackPeriodMonths = monthlyRevenue > 0 ? avgCAC / monthlyRevenue : 0;
383
+ return {
384
+ ratio,
385
+ avgLTV,
386
+ avgCAC,
387
+ paybackPeriodMonths,
388
+ segment,
389
+ isHealthy: ratio > 3,
390
+ };
391
+ }
392
+ // ============================================================================
393
+ // Statistical Significance Functions
394
+ // ============================================================================
395
+ /**
396
+ * Calculate the cumulative distribution function for standard normal distribution
397
+ * Using approximation formula
398
+ */
399
+ function normalCDF(z) {
400
+ const a1 = 0.254829592;
401
+ const a2 = -0.284496736;
402
+ const a3 = 1.421413741;
403
+ const a4 = -1.453152027;
404
+ const a5 = 1.061405429;
405
+ const p = 0.3275911;
406
+ const sign = z < 0 ? -1 : 1;
407
+ z = Math.abs(z) / Math.sqrt(2);
408
+ const t = 1.0 / (1.0 + p * z);
409
+ const y = 1.0 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-z * z);
410
+ return 0.5 * (1.0 + sign * y);
411
+ }
412
+ /**
413
+ * Calculate the inverse of the cumulative distribution function (quantile function)
414
+ * Using Abramowitz and Stegun approximation
415
+ */
416
+ function normalQuantile(p) {
417
+ if (p <= 0)
418
+ return -Infinity;
419
+ if (p >= 1)
420
+ return Infinity;
421
+ if (p === 0.5)
422
+ return 0;
423
+ // Rational approximation for lower region
424
+ const a = [
425
+ -3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2, 1.383577518672690e2, -3.066479806614716e1,
426
+ 2.506628277459239e0,
427
+ ];
428
+ const b = [
429
+ -5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2, 6.680131188771972e1, -1.328068155288572e1,
430
+ ];
431
+ const c = [
432
+ -7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838e0, -2.549732539343734e0, 4.374664141464968e0,
433
+ 2.938163982698783e0,
434
+ ];
435
+ const d = [7.784695709041462e-3, 3.224671290700398e-1, 2.445134137142996e0, 3.754408661907416e0];
436
+ const pLow = 0.02425;
437
+ const pHigh = 1 - pLow;
438
+ let q, r;
439
+ if (p < pLow) {
440
+ q = Math.sqrt(-2 * Math.log(p));
441
+ return (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
442
+ }
443
+ else if (p <= pHigh) {
444
+ q = p - 0.5;
445
+ r = q * q;
446
+ return (((((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q) /
447
+ (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1));
448
+ }
449
+ else {
450
+ q = Math.sqrt(-2 * Math.log(1 - p));
451
+ return -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
452
+ }
453
+ }
454
+ /**
455
+ * Calculate statistical significance for an A/B test experiment
456
+ */
457
+ async function calculateSignificance(experimentId, metric, variant, control) {
458
+ const experiment = mockData.experiments.get(experimentId);
459
+ if (!experiment) {
460
+ // Return a non-significant result for missing experiments
461
+ return {
462
+ experimentId,
463
+ variant,
464
+ control,
465
+ metric,
466
+ sampleSizeVariant: 0,
467
+ sampleSizeControl: 0,
468
+ conversionVariant: 0,
469
+ conversionControl: 0,
470
+ pValue: 1,
471
+ confidenceLevel: 0,
472
+ isSignificant: false,
473
+ lift: 0,
474
+ confidenceInterval: [0, 0],
475
+ };
476
+ }
477
+ const variantData = experiment.variants.get(variant) || { samples: 0, conversions: 0 };
478
+ const controlData = experiment.variants.get(control) || { samples: 0, conversions: 0 };
479
+ const n1 = variantData.samples;
480
+ const n2 = controlData.samples;
481
+ const x1 = variantData.conversions;
482
+ const x2 = controlData.conversions;
483
+ const p1 = n1 > 0 ? x1 / n1 : 0;
484
+ const p2 = n2 > 0 ? x2 / n2 : 0;
485
+ // Pooled proportion for two-proportion z-test
486
+ const pPooled = (n1 + n2) > 0 ? (x1 + x2) / (n1 + n2) : 0;
487
+ // Standard error
488
+ const se = Math.sqrt(pPooled * (1 - pPooled) * (1 / n1 + 1 / n2)) || 0.0001;
489
+ // Z-score
490
+ const z = (p1 - p2) / se;
491
+ // Two-tailed p-value
492
+ const pValue = 2 * (1 - normalCDF(Math.abs(z)));
493
+ // Confidence interval for the difference (95%)
494
+ const seDiff = Math.sqrt((p1 * (1 - p1)) / n1 + (p2 * (1 - p2)) / n2) || 0.0001;
495
+ const zCritical = 1.96; // 95% confidence
496
+ const diff = p1 - p2;
497
+ const marginOfError = zCritical * seDiff;
498
+ const confidenceInterval = [diff - marginOfError, diff + marginOfError];
499
+ // Lift percentage
500
+ const lift = p2 > 0 ? ((p1 - p2) / p2) * 100 : 0;
501
+ // For small samples, mark as not significant
502
+ const isSignificant = n1 >= 30 && n2 >= 30 && pValue < 0.05;
503
+ return {
504
+ experimentId,
505
+ variant,
506
+ control,
507
+ metric,
508
+ sampleSizeVariant: n1,
509
+ sampleSizeControl: n2,
510
+ conversionVariant: p1,
511
+ conversionControl: p2,
512
+ pValue,
513
+ confidenceLevel: 1 - pValue,
514
+ isSignificant,
515
+ lift,
516
+ confidenceInterval,
517
+ };
518
+ }
519
+ /**
520
+ * Calculate required sample size for desired statistical power
521
+ * Using formula for two-proportion test
522
+ */
523
+ function calculateSampleSize(baselineConversion, minDetectableEffect, power, significanceLevel) {
524
+ // Handle edge cases
525
+ if (baselineConversion <= 0 || baselineConversion >= 1) {
526
+ // Return a reasonable default for edge cases
527
+ return 1000;
528
+ }
529
+ // Expected conversion rate for variant
530
+ const p1 = baselineConversion;
531
+ const p2 = baselineConversion * (1 + minDetectableEffect);
532
+ // Clamp p2 to valid range
533
+ const p2Clamped = Math.min(Math.max(p2, 0.001), 0.999);
534
+ // Z-scores for significance and power
535
+ const zAlpha = normalQuantile(1 - significanceLevel / 2); // Two-tailed
536
+ const zBeta = normalQuantile(power);
537
+ // Pooled standard deviation
538
+ const pAvg = (p1 + p2Clamped) / 2;
539
+ const sd = Math.sqrt(2 * pAvg * (1 - pAvg));
540
+ // Effect size
541
+ const effect = Math.abs(p2Clamped - p1);
542
+ if (effect === 0) {
543
+ return Infinity;
544
+ }
545
+ // Sample size per group
546
+ const n = Math.pow((zAlpha + zBeta) * sd / effect, 2);
547
+ return Math.ceil(n);
548
+ }
549
+ // ============================================================================
550
+ // Dashboard Functions
551
+ // ============================================================================
552
+ /**
553
+ * Calculate composite PMF score from HUNCH metrics
554
+ * Weights:
555
+ * - Hair-on-fire: 25% (problem urgency)
556
+ * - Usage: 20% (engagement)
557
+ * - NPS: 20% (satisfaction)
558
+ * - Churn: 20% (retention)
559
+ * - LTV/CAC: 15% (unit economics)
560
+ */
561
+ function calculatePMFScore(dashboard) {
562
+ // Hair-on-fire: 0-10 scale -> 0-100
563
+ const hofScore = (dashboard.hairOnFire.score / 10) * 100;
564
+ // Usage: DAU/WAU ratio, typically 0.2-0.5 is good
565
+ // Map 0-0.5 to 0-100
566
+ const usageScore = Math.min((dashboard.usage.dauWauRatio / 0.5) * 100, 100);
567
+ // NPS: -100 to 100 -> 0 to 100
568
+ const npsScore = (dashboard.nps.score + 100) / 2;
569
+ // Churn: Lower is better. 0% = 100, 20%+ = 0
570
+ const churnScore = Math.max(0, (1 - dashboard.churn.monthlyChurnRate / 0.2) * 100);
571
+ // LTV/CAC: Ratio of 5+ is excellent (100), below 1 is poor (0)
572
+ const ltvCacScore = Math.min(dashboard.ltvCac.ratio / 5 * 100, 100);
573
+ // Weighted average
574
+ const pmfScore = hofScore * 0.25 +
575
+ usageScore * 0.20 +
576
+ npsScore * 0.20 +
577
+ churnScore * 0.20 +
578
+ ltvCacScore * 0.15;
579
+ return Math.round(Math.max(0, Math.min(100, pmfScore)));
580
+ }
581
+ /**
582
+ * Get complete HUNCH dashboard data
583
+ */
584
+ async function getHUNCHDashboard() {
585
+ // Gather all metrics
586
+ const now = new Date();
587
+ // NPS
588
+ const npsTrend = await getNPSTrend(30);
589
+ const latestNPS = npsTrend[npsTrend.length - 1] || calculateNPS([]);
590
+ // Churn
591
+ const monthlyChurnRate = await calculateChurnRate({
592
+ start: new Date(now.getFullYear(), now.getMonth() - 1, 1),
593
+ end: now,
594
+ });
595
+ const annualChurnRate = 1 - Math.pow(1 - monthlyChurnRate, 12);
596
+ // Build retention curve from cohorts
597
+ const cohorts = [];
598
+ for (const [, cohortData] of mockData.cohorts) {
599
+ cohorts.push({
600
+ cohortId: 'mock',
601
+ cohortDate: new Date(),
602
+ initialUsers: cohortData.initialUsers,
603
+ retainedByPeriod: cohortData.retainedByMonth.map((count, i) => ({
604
+ period: i + 1,
605
+ count,
606
+ rate: count / cohortData.initialUsers,
607
+ })),
608
+ churned: cohortData.initialUsers - (cohortData.retainedByMonth[cohortData.retainedByMonth.length - 1] || 0),
609
+ churnRate: 1 - (cohortData.retainedByMonth[cohortData.retainedByMonth.length - 1] || 0) / cohortData.initialUsers,
610
+ });
611
+ }
612
+ const retentionCurve = buildRetentionCurve(cohorts);
613
+ // LTV/CAC
614
+ const ltvCac = await calculateLTVCACRatio();
615
+ // Build dashboard without score and alerts first
616
+ const dashboardData = {
617
+ asOf: now,
618
+ hairOnFire: {
619
+ score: mockData.hairOnFireScore,
620
+ signals: mockData.hairOnFireSignals,
621
+ },
622
+ usage: {
623
+ dau: mockData.usage.dau,
624
+ wau: mockData.usage.wau,
625
+ mau: mockData.usage.mau,
626
+ dauWauRatio: mockData.usage.dau / mockData.usage.wau,
627
+ growthRate: mockData.usage.growthRate,
628
+ },
629
+ nps: latestNPS,
630
+ churn: {
631
+ monthlyChurnRate,
632
+ annualChurnRate,
633
+ retentionCurve,
634
+ },
635
+ ltvCac,
636
+ };
637
+ // Calculate PMF score
638
+ const overallPMFScore = calculatePMFScore(dashboardData);
639
+ // Check thresholds for alerts
640
+ const alerts = await checkThresholds();
641
+ return {
642
+ ...dashboardData,
643
+ overallPMFScore,
644
+ alerts,
645
+ };
646
+ }
647
+ // ============================================================================
648
+ // Alert Functions
649
+ // ============================================================================
650
+ /**
651
+ * Set a metric threshold
652
+ */
653
+ function setThreshold(metric, threshold, operator, severity) {
654
+ // Remove existing threshold for this metric
655
+ const existingIndex = thresholds.findIndex((t) => t.metric === metric);
656
+ if (existingIndex >= 0) {
657
+ thresholds.splice(existingIndex, 1);
658
+ }
659
+ // Add new threshold
660
+ thresholds.push({ metric, threshold, operator, severity });
661
+ }
662
+ /**
663
+ * Check all thresholds and return alerts for breached ones
664
+ */
665
+ async function checkThresholds() {
666
+ const alerts = [];
667
+ const now = new Date();
668
+ // Get current metric values
669
+ const dashboard = {
670
+ nps: (await getNPSTrend(7))[0]?.score ?? 50,
671
+ monthly_churn_rate: await calculateChurnRate({
672
+ start: new Date(now.getFullYear(), now.getMonth() - 1, 1),
673
+ end: now,
674
+ }),
675
+ ltv_cac_ratio: (await calculateLTVCACRatio()).ratio,
676
+ dau_wau_ratio: mockData.usage.dau / mockData.usage.wau,
677
+ };
678
+ const metricValues = dashboard;
679
+ for (const config of thresholds) {
680
+ const currentValue = metricValues[config.metric];
681
+ if (currentValue === undefined)
682
+ continue;
683
+ let isBreached = false;
684
+ switch (config.operator) {
685
+ case 'gt':
686
+ isBreached = currentValue > config.threshold;
687
+ break;
688
+ case 'lt':
689
+ isBreached = currentValue < config.threshold;
690
+ break;
691
+ case 'eq':
692
+ isBreached = currentValue === config.threshold;
693
+ break;
694
+ }
695
+ if (isBreached) {
696
+ alerts.push({
697
+ id: `alert-${config.metric}-${Date.now()}`,
698
+ metric: config.metric,
699
+ threshold: config.threshold,
700
+ currentValue,
701
+ operator: config.operator,
702
+ severity: config.severity,
703
+ message: `${config.metric} is ${config.operator === 'gt' ? 'above' : config.operator === 'lt' ? 'below' : 'at'} threshold: ${currentValue.toFixed(2)} ${config.operator} ${config.threshold}`,
704
+ triggeredAt: now,
705
+ });
706
+ }
707
+ }
708
+ return alerts;
709
+ }
710
+ // ============================================================================
711
+ // Export HUNCHMetrics Module
712
+ // ============================================================================
713
+ export const HUNCHMetrics = {
714
+ // NPS
715
+ calculateNPS,
716
+ aggregateNPSBySegment,
717
+ getNPSTrend,
718
+ // Churn
719
+ calculateCohortRetention,
720
+ calculateChurnRate,
721
+ buildRetentionCurve,
722
+ predictChurn,
723
+ // LTV/CAC
724
+ calculateCustomerLTV,
725
+ calculateAverageLTV,
726
+ calculateCAC,
727
+ calculateLTVCACRatio,
728
+ // Statistical Significance
729
+ calculateSignificance,
730
+ calculateSampleSize,
731
+ // Dashboard
732
+ getHUNCHDashboard,
733
+ calculatePMFScore,
734
+ // Alerts
735
+ checkThresholds,
736
+ setThreshold,
737
+ };
738
+ export default HUNCHMetrics;
739
+ //# sourceMappingURL=hunch.js.map