@shware/workflow 4.1.1 → 5.0.1

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 (485) hide show
  1. package/README.md +16 -38
  2. package/dist/_virtual/_rolldown/runtime.cjs +1 -2
  3. package/dist/apns-relay.cjs +1 -2
  4. package/dist/apns-relay.d.cts +0 -2
  5. package/dist/apns-relay.d.cts.map +1 -1
  6. package/dist/apns-relay.d.mts +0 -2
  7. package/dist/apns-relay.d.mts.map +1 -1
  8. package/dist/apns-relay.mjs +1 -2
  9. package/dist/apns.cjs +1 -2
  10. package/dist/apns.d.cts +0 -2
  11. package/dist/apns.d.cts.map +1 -1
  12. package/dist/apns.d.mts +0 -2
  13. package/dist/apns.d.mts.map +1 -1
  14. package/dist/apns.mjs +1 -2
  15. package/dist/aws/engine-step.cjs +1 -2
  16. package/dist/aws/engine-step.d.cts +0 -2
  17. package/dist/aws/engine-step.d.cts.map +1 -1
  18. package/dist/aws/engine-step.d.mts +0 -2
  19. package/dist/aws/engine-step.d.mts.map +1 -1
  20. package/dist/aws/engine-step.mjs +1 -2
  21. package/dist/aws/function-url.cjs +1 -2
  22. package/dist/aws/function-url.d.cts +0 -2
  23. package/dist/aws/function-url.d.cts.map +1 -1
  24. package/dist/aws/function-url.d.mts +0 -2
  25. package/dist/aws/function-url.d.mts.map +1 -1
  26. package/dist/aws/function-url.mjs +1 -2
  27. package/dist/aws/index.cjs +3 -5
  28. package/dist/aws/index.cjs.map +1 -1
  29. package/dist/aws/index.d.cts +1 -3
  30. package/dist/aws/index.d.cts.map +1 -1
  31. package/dist/aws/index.d.mts +1 -3
  32. package/dist/aws/index.d.mts.map +1 -1
  33. package/dist/aws/index.mjs +3 -5
  34. package/dist/aws/index.mjs.map +1 -1
  35. package/dist/aws/instances.cjs +2 -3
  36. package/dist/aws/instances.cjs.map +1 -1
  37. package/dist/aws/instances.d.cts +1 -3
  38. package/dist/aws/instances.d.cts.map +1 -1
  39. package/dist/aws/instances.d.mts +1 -3
  40. package/dist/aws/instances.d.mts.map +1 -1
  41. package/dist/aws/instances.mjs +2 -3
  42. package/dist/aws/instances.mjs.map +1 -1
  43. package/dist/aws/lambda-api.cjs +1 -2
  44. package/dist/aws/lambda-api.d.cts +0 -2
  45. package/dist/aws/lambda-api.d.cts.map +1 -1
  46. package/dist/aws/lambda-api.d.mts +0 -2
  47. package/dist/aws/lambda-api.d.mts.map +1 -1
  48. package/dist/aws/lambda-api.mjs +1 -2
  49. package/dist/client.cjs +1 -2
  50. package/dist/client.d.cts +0 -2
  51. package/dist/client.d.cts.map +1 -1
  52. package/dist/client.d.mts +0 -2
  53. package/dist/client.d.mts.map +1 -1
  54. package/dist/client.mjs +1 -2
  55. package/dist/cloudflare/bindings.cjs +1 -2
  56. package/dist/cloudflare/bindings.cjs.map +1 -1
  57. package/dist/cloudflare/bindings.d.cts +0 -21
  58. package/dist/cloudflare/bindings.d.cts.map +1 -1
  59. package/dist/cloudflare/bindings.d.mts +0 -21
  60. package/dist/cloudflare/bindings.d.mts.map +1 -1
  61. package/dist/cloudflare/bindings.mjs +1 -2
  62. package/dist/cloudflare/bindings.mjs.map +1 -1
  63. package/dist/cloudflare/index.cjs +0 -5
  64. package/dist/cloudflare/index.d.cts +4 -6
  65. package/dist/cloudflare/index.d.mts +4 -6
  66. package/dist/cloudflare/index.mjs +2 -4
  67. package/dist/cloudflare/runner.cjs +4 -6
  68. package/dist/cloudflare/runner.cjs.map +1 -1
  69. package/dist/cloudflare/runner.d.cts +3 -5
  70. package/dist/cloudflare/runner.d.cts.map +1 -1
  71. package/dist/cloudflare/runner.d.mts +3 -5
  72. package/dist/cloudflare/runner.d.mts.map +1 -1
  73. package/dist/cloudflare/runner.mjs +4 -6
  74. package/dist/cloudflare/runner.mjs.map +1 -1
  75. package/dist/cloudflare/worker.cjs +1 -2
  76. package/dist/cloudflare/worker.d.cts +0 -2
  77. package/dist/cloudflare/worker.d.cts.map +1 -1
  78. package/dist/cloudflare/worker.d.mts +0 -2
  79. package/dist/cloudflare/worker.d.mts.map +1 -1
  80. package/dist/cloudflare/worker.mjs +1 -2
  81. package/dist/cloudflare/workers.d.cts +0 -2
  82. package/dist/cloudflare/workers.d.cts.map +1 -1
  83. package/dist/cloudflare/workers.d.mts +0 -2
  84. package/dist/cloudflare/workers.d.mts.map +1 -1
  85. package/dist/config.cjs +1 -2
  86. package/dist/config.cjs.map +1 -1
  87. package/dist/config.d.cts +1 -3
  88. package/dist/config.d.cts.map +1 -1
  89. package/dist/config.d.mts +1 -3
  90. package/dist/config.d.mts.map +1 -1
  91. package/dist/config.mjs +1 -2
  92. package/dist/config.mjs.map +1 -1
  93. package/dist/contract.cjs +1 -2
  94. package/dist/contract.d.cts +0 -2
  95. package/dist/contract.d.cts.map +1 -1
  96. package/dist/contract.d.mts +0 -2
  97. package/dist/contract.d.mts.map +1 -1
  98. package/dist/contract.mjs +1 -2
  99. package/dist/dsl/action.cjs +1 -2
  100. package/dist/dsl/action.d.cts +0 -2
  101. package/dist/dsl/action.d.cts.map +1 -1
  102. package/dist/dsl/action.d.mts +0 -2
  103. package/dist/dsl/action.d.mts.map +1 -1
  104. package/dist/dsl/action.mjs +1 -2
  105. package/dist/dsl/base.cjs +1 -2
  106. package/dist/dsl/base.d.cts +0 -2
  107. package/dist/dsl/base.d.cts.map +1 -1
  108. package/dist/dsl/base.d.mts +0 -2
  109. package/dist/dsl/base.d.mts.map +1 -1
  110. package/dist/dsl/base.mjs +1 -2
  111. package/dist/dsl/bundle.cjs +1 -2
  112. package/dist/dsl/bundle.d.cts +0 -2
  113. package/dist/dsl/bundle.d.cts.map +1 -1
  114. package/dist/dsl/bundle.d.mts +0 -2
  115. package/dist/dsl/bundle.d.mts.map +1 -1
  116. package/dist/dsl/bundle.mjs +1 -2
  117. package/dist/dsl/condition.cjs +1 -2
  118. package/dist/dsl/condition.d.cts +0 -2
  119. package/dist/dsl/condition.d.cts.map +1 -1
  120. package/dist/dsl/condition.d.mts +0 -2
  121. package/dist/dsl/condition.d.mts.map +1 -1
  122. package/dist/dsl/condition.mjs +1 -2
  123. package/dist/dsl/flow.cjs +1 -2
  124. package/dist/dsl/flow.d.cts +0 -2
  125. package/dist/dsl/flow.d.cts.map +1 -1
  126. package/dist/dsl/flow.d.mts +0 -2
  127. package/dist/dsl/flow.d.mts.map +1 -1
  128. package/dist/dsl/flow.mjs +1 -2
  129. package/dist/dsl/refs.cjs +1 -2
  130. package/dist/dsl/refs.d.cts +0 -2
  131. package/dist/dsl/refs.d.cts.map +1 -1
  132. package/dist/dsl/refs.d.mts +0 -2
  133. package/dist/dsl/refs.d.mts.map +1 -1
  134. package/dist/dsl/refs.mjs +1 -2
  135. package/dist/dsl/template.cjs +1 -2
  136. package/dist/dsl/template.d.cts +0 -2
  137. package/dist/dsl/template.d.cts.map +1 -1
  138. package/dist/dsl/template.d.mts +0 -2
  139. package/dist/dsl/template.d.mts.map +1 -1
  140. package/dist/dsl/template.mjs +1 -2
  141. package/dist/dsl/trigger.cjs +1 -2
  142. package/dist/dsl/trigger.d.cts +0 -2
  143. package/dist/dsl/trigger.d.cts.map +1 -1
  144. package/dist/dsl/trigger.d.mts +0 -2
  145. package/dist/dsl/trigger.d.mts.map +1 -1
  146. package/dist/dsl/trigger.mjs +1 -2
  147. package/dist/dsl/workflow.cjs +1 -2
  148. package/dist/dsl/workflow.d.cts +0 -2
  149. package/dist/dsl/workflow.d.cts.map +1 -1
  150. package/dist/dsl/workflow.d.mts +0 -2
  151. package/dist/dsl/workflow.d.mts.map +1 -1
  152. package/dist/dsl/workflow.mjs +1 -2
  153. package/dist/email-context.cjs +1 -2
  154. package/dist/email-context.d.cts +0 -2
  155. package/dist/email-context.d.cts.map +1 -1
  156. package/dist/email-context.d.mts +0 -2
  157. package/dist/email-context.d.mts.map +1 -1
  158. package/dist/email-context.mjs +1 -2
  159. package/dist/email-sender.cjs +1 -2
  160. package/dist/email-sender.d.cts +0 -2
  161. package/dist/email-sender.d.cts.map +1 -1
  162. package/dist/email-sender.d.mts +0 -2
  163. package/dist/email-sender.d.mts.map +1 -1
  164. package/dist/email-sender.mjs +1 -2
  165. package/dist/email.cjs +1 -2
  166. package/dist/email.d.cts +0 -2
  167. package/dist/email.d.cts.map +1 -1
  168. package/dist/email.d.mts +0 -2
  169. package/dist/email.d.mts.map +1 -1
  170. package/dist/email.mjs +1 -2
  171. package/dist/engine/actions.cjs +1 -2
  172. package/dist/engine/actions.d.cts +0 -2
  173. package/dist/engine/actions.d.cts.map +1 -1
  174. package/dist/engine/actions.d.mts +0 -2
  175. package/dist/engine/actions.d.mts.map +1 -1
  176. package/dist/engine/actions.mjs +1 -2
  177. package/dist/engine/bucket.cjs +1 -2
  178. package/dist/engine/bucket.d.cts +0 -2
  179. package/dist/engine/bucket.d.cts.map +1 -1
  180. package/dist/engine/bucket.d.mts +0 -2
  181. package/dist/engine/bucket.d.mts.map +1 -1
  182. package/dist/engine/bucket.mjs +1 -2
  183. package/dist/engine/condition.cjs +3 -4
  184. package/dist/engine/condition.cjs.map +1 -1
  185. package/dist/engine/condition.d.cts +1 -3
  186. package/dist/engine/condition.d.cts.map +1 -1
  187. package/dist/engine/condition.d.mts +1 -3
  188. package/dist/engine/condition.d.mts.map +1 -1
  189. package/dist/engine/condition.mjs +3 -4
  190. package/dist/engine/condition.mjs.map +1 -1
  191. package/dist/engine/duration.cjs +1 -2
  192. package/dist/engine/duration.d.cts +0 -2
  193. package/dist/engine/duration.d.cts.map +1 -1
  194. package/dist/engine/duration.d.mts +0 -2
  195. package/dist/engine/duration.d.mts.map +1 -1
  196. package/dist/engine/duration.mjs +1 -2
  197. package/dist/engine/interpreter.cjs +1 -2
  198. package/dist/engine/interpreter.d.cts +0 -2
  199. package/dist/engine/interpreter.d.cts.map +1 -1
  200. package/dist/engine/interpreter.d.mts +0 -2
  201. package/dist/engine/interpreter.d.mts.map +1 -1
  202. package/dist/engine/interpreter.mjs +1 -2
  203. package/dist/engine/ports.d.cts +1 -3
  204. package/dist/engine/ports.d.cts.map +1 -1
  205. package/dist/engine/ports.d.mts +1 -3
  206. package/dist/engine/ports.d.mts.map +1 -1
  207. package/dist/engine/recipient.cjs +1 -2
  208. package/dist/engine/recipient.d.cts +0 -2
  209. package/dist/engine/recipient.d.cts.map +1 -1
  210. package/dist/engine/recipient.d.mts +0 -2
  211. package/dist/engine/recipient.d.mts.map +1 -1
  212. package/dist/engine/recipient.mjs +1 -2
  213. package/dist/engine/retry.cjs +1 -2
  214. package/dist/engine/retry.d.cts +0 -2
  215. package/dist/engine/retry.d.cts.map +1 -1
  216. package/dist/engine/retry.d.mts +0 -2
  217. package/dist/engine/retry.d.mts.map +1 -1
  218. package/dist/engine/retry.mjs +1 -2
  219. package/dist/engine/time-scale.cjs +1 -2
  220. package/dist/engine/time-scale.d.cts +0 -2
  221. package/dist/engine/time-scale.d.cts.map +1 -1
  222. package/dist/engine/time-scale.d.mts +0 -2
  223. package/dist/engine/time-scale.d.mts.map +1 -1
  224. package/dist/engine/time-scale.mjs +1 -2
  225. package/dist/engine/time-window.cjs +1 -2
  226. package/dist/engine/time-window.d.cts +0 -2
  227. package/dist/engine/time-window.d.cts.map +1 -1
  228. package/dist/engine/time-window.d.mts +0 -2
  229. package/dist/engine/time-window.d.mts.map +1 -1
  230. package/dist/engine/time-window.mjs +1 -2
  231. package/dist/fcm.cjs +1 -2
  232. package/dist/fcm.d.cts +0 -2
  233. package/dist/fcm.d.cts.map +1 -1
  234. package/dist/fcm.d.mts +0 -2
  235. package/dist/fcm.d.mts.map +1 -1
  236. package/dist/fcm.mjs +1 -2
  237. package/dist/hash.cjs +1 -2
  238. package/dist/hash.d.cts +0 -2
  239. package/dist/hash.d.cts.map +1 -1
  240. package/dist/hash.d.mts +0 -2
  241. package/dist/hash.d.mts.map +1 -1
  242. package/dist/hash.mjs +1 -2
  243. package/dist/host/auth.cjs +1 -2
  244. package/dist/host/auth.d.cts +0 -2
  245. package/dist/host/auth.d.cts.map +1 -1
  246. package/dist/host/auth.d.mts +0 -2
  247. package/dist/host/auth.d.mts.map +1 -1
  248. package/dist/host/auth.mjs +1 -2
  249. package/dist/host/channels.cjs +1 -2
  250. package/dist/host/channels.d.cts +1 -3
  251. package/dist/host/channels.d.cts.map +1 -1
  252. package/dist/host/channels.d.mts +1 -3
  253. package/dist/host/channels.d.mts.map +1 -1
  254. package/dist/host/channels.mjs +1 -2
  255. package/dist/host/execute.cjs +1 -2
  256. package/dist/host/execute.d.cts +1 -3
  257. package/dist/host/execute.d.cts.map +1 -1
  258. package/dist/host/execute.d.mts +1 -3
  259. package/dist/host/execute.d.mts.map +1 -1
  260. package/dist/host/execute.mjs +1 -2
  261. package/dist/host/fresh-read.cjs +1 -2
  262. package/dist/host/fresh-read.d.cts +0 -2
  263. package/dist/host/fresh-read.d.cts.map +1 -1
  264. package/dist/host/fresh-read.d.mts +0 -2
  265. package/dist/host/fresh-read.d.mts.map +1 -1
  266. package/dist/host/fresh-read.mjs +1 -2
  267. package/dist/host/http.cjs +4 -6
  268. package/dist/host/http.cjs.map +1 -1
  269. package/dist/host/http.d.cts +2 -4
  270. package/dist/host/http.d.cts.map +1 -1
  271. package/dist/host/http.d.mts +2 -4
  272. package/dist/host/http.d.mts.map +1 -1
  273. package/dist/host/http.mjs +4 -6
  274. package/dist/host/http.mjs.map +1 -1
  275. package/dist/host/ingest.cjs +12 -24
  276. package/dist/host/ingest.cjs.map +1 -1
  277. package/dist/host/ingest.d.cts +8 -15
  278. package/dist/host/ingest.d.cts.map +1 -1
  279. package/dist/host/ingest.d.mts +8 -15
  280. package/dist/host/ingest.d.mts.map +1 -1
  281. package/dist/host/ingest.mjs +13 -24
  282. package/dist/host/ingest.mjs.map +1 -1
  283. package/dist/host/journey-host.cjs +3 -6
  284. package/dist/host/journey-host.cjs.map +1 -1
  285. package/dist/host/journey-host.d.cts +6 -8
  286. package/dist/host/journey-host.d.cts.map +1 -1
  287. package/dist/host/journey-host.d.mts +6 -8
  288. package/dist/host/journey-host.d.mts.map +1 -1
  289. package/dist/host/journey-host.mjs +3 -6
  290. package/dist/host/journey-host.mjs.map +1 -1
  291. package/dist/host/platform.cjs +1 -2
  292. package/dist/host/platform.cjs.map +1 -1
  293. package/dist/host/platform.d.cts +1 -9
  294. package/dist/host/platform.d.cts.map +1 -1
  295. package/dist/host/platform.d.mts +1 -9
  296. package/dist/host/platform.d.mts.map +1 -1
  297. package/dist/host/platform.mjs +1 -2
  298. package/dist/host/platform.mjs.map +1 -1
  299. package/dist/host/senders.cjs +1 -2
  300. package/dist/host/senders.d.cts +0 -2
  301. package/dist/host/senders.d.cts.map +1 -1
  302. package/dist/host/senders.d.mts +0 -2
  303. package/dist/host/senders.d.mts.map +1 -1
  304. package/dist/host/senders.mjs +1 -2
  305. package/dist/http2-client.cjs +1 -2
  306. package/dist/http2-client.d.cts +0 -2
  307. package/dist/http2-client.d.cts.map +1 -1
  308. package/dist/http2-client.d.mts +0 -2
  309. package/dist/http2-client.d.mts.map +1 -1
  310. package/dist/http2-client.mjs +1 -2
  311. package/dist/ir.cjs +1 -2
  312. package/dist/ir.d.cts +0 -2
  313. package/dist/ir.d.cts.map +1 -1
  314. package/dist/ir.d.mts +0 -2
  315. package/dist/ir.d.mts.map +1 -1
  316. package/dist/ir.mjs +1 -2
  317. package/dist/jwt.cjs +1 -2
  318. package/dist/jwt.d.cts +0 -2
  319. package/dist/jwt.d.cts.map +1 -1
  320. package/dist/jwt.d.mts +0 -2
  321. package/dist/jwt.d.mts.map +1 -1
  322. package/dist/jwt.mjs +1 -2
  323. package/dist/plan.cjs +1 -2
  324. package/dist/plan.d.cts +0 -2
  325. package/dist/plan.d.cts.map +1 -1
  326. package/dist/plan.d.mts +0 -2
  327. package/dist/plan.d.mts.map +1 -1
  328. package/dist/plan.mjs +1 -2
  329. package/dist/postgres-js.cjs +1 -2
  330. package/dist/postgres-js.d.cts +0 -2
  331. package/dist/postgres-js.d.cts.map +1 -1
  332. package/dist/postgres-js.d.mts +0 -2
  333. package/dist/postgres-js.d.mts.map +1 -1
  334. package/dist/postgres-js.mjs +1 -2
  335. package/dist/provenance.cjs +1 -2
  336. package/dist/provenance.d.cts +0 -2
  337. package/dist/provenance.d.cts.map +1 -1
  338. package/dist/provenance.d.mts +0 -2
  339. package/dist/provenance.d.mts.map +1 -1
  340. package/dist/provenance.mjs +1 -2
  341. package/dist/push.cjs +1 -2
  342. package/dist/push.d.cts +0 -2
  343. package/dist/push.d.cts.map +1 -1
  344. package/dist/push.d.mts +0 -2
  345. package/dist/push.d.mts.map +1 -1
  346. package/dist/push.mjs +1 -2
  347. package/dist/react-email.cjs +1 -2
  348. package/dist/react-email.d.cts +0 -2
  349. package/dist/react-email.d.cts.map +1 -1
  350. package/dist/react-email.d.mts +0 -2
  351. package/dist/react-email.d.mts.map +1 -1
  352. package/dist/react-email.mjs +1 -2
  353. package/dist/reporting/classify.cjs +1 -2
  354. package/dist/reporting/classify.d.cts +0 -2
  355. package/dist/reporting/classify.d.cts.map +1 -1
  356. package/dist/reporting/classify.d.mts +0 -2
  357. package/dist/reporting/classify.d.mts.map +1 -1
  358. package/dist/reporting/classify.mjs +1 -2
  359. package/dist/reporting/observer.cjs +1 -2
  360. package/dist/reporting/observer.d.cts +0 -2
  361. package/dist/reporting/observer.d.cts.map +1 -1
  362. package/dist/reporting/observer.d.mts +0 -2
  363. package/dist/reporting/observer.d.mts.map +1 -1
  364. package/dist/reporting/observer.mjs +1 -2
  365. package/dist/reporting/tracking.cjs +1 -2
  366. package/dist/reporting/tracking.d.cts +0 -2
  367. package/dist/reporting/tracking.d.cts.map +1 -1
  368. package/dist/reporting/tracking.d.mts +0 -2
  369. package/dist/reporting/tracking.d.mts.map +1 -1
  370. package/dist/reporting/tracking.mjs +1 -2
  371. package/dist/runtime.cjs +1 -2
  372. package/dist/runtime.d.cts +0 -2
  373. package/dist/runtime.d.cts.map +1 -1
  374. package/dist/runtime.d.mts +0 -2
  375. package/dist/runtime.d.mts.map +1 -1
  376. package/dist/runtime.mjs +1 -2
  377. package/dist/store/erasure.cjs +1 -2
  378. package/dist/store/erasure.d.cts +0 -2
  379. package/dist/store/erasure.d.cts.map +1 -1
  380. package/dist/store/erasure.d.mts +0 -2
  381. package/dist/store/erasure.d.mts.map +1 -1
  382. package/dist/store/erasure.mjs +1 -2
  383. package/dist/store/facts.cjs +2 -3
  384. package/dist/store/facts.cjs.map +1 -1
  385. package/dist/store/facts.d.cts +0 -2
  386. package/dist/store/facts.d.cts.map +1 -1
  387. package/dist/store/facts.d.mts +0 -2
  388. package/dist/store/facts.d.mts.map +1 -1
  389. package/dist/store/facts.mjs +2 -3
  390. package/dist/store/facts.mjs.map +1 -1
  391. package/dist/store/index.cjs +1 -4
  392. package/dist/store/index.cjs.map +1 -1
  393. package/dist/store/index.d.cts +21 -28
  394. package/dist/store/index.d.cts.map +1 -1
  395. package/dist/store/index.d.mts +21 -28
  396. package/dist/store/index.d.mts.map +1 -1
  397. package/dist/store/index.mjs +2 -4
  398. package/dist/store/index.mjs.map +1 -1
  399. package/dist/store/postgres-reporting.cjs +1 -2
  400. package/dist/store/postgres-reporting.d.cts +0 -2
  401. package/dist/store/postgres-reporting.d.cts.map +1 -1
  402. package/dist/store/postgres-reporting.d.mts +0 -2
  403. package/dist/store/postgres-reporting.d.mts.map +1 -1
  404. package/dist/store/postgres-reporting.mjs +1 -2
  405. package/dist/store/postgres.cjs +3 -5
  406. package/dist/store/postgres.cjs.map +1 -1
  407. package/dist/store/postgres.d.cts +2 -5
  408. package/dist/store/postgres.d.cts.map +1 -1
  409. package/dist/store/postgres.d.mts +2 -5
  410. package/dist/store/postgres.d.mts.map +1 -1
  411. package/dist/store/postgres.mjs +3 -5
  412. package/dist/store/postgres.mjs.map +1 -1
  413. package/dist/store/sql.cjs +1 -2
  414. package/dist/store/sql.d.cts +0 -2
  415. package/dist/store/sql.d.cts.map +1 -1
  416. package/dist/store/sql.d.mts +0 -2
  417. package/dist/store/sql.d.mts.map +1 -1
  418. package/dist/store/sql.mjs +1 -2
  419. package/dist/store/tables.cjs +1 -2
  420. package/dist/store/tables.d.cts +0 -2
  421. package/dist/store/tables.d.cts.map +1 -1
  422. package/dist/store/tables.d.mts +0 -2
  423. package/dist/store/tables.d.mts.map +1 -1
  424. package/dist/store/tables.mjs +1 -2
  425. package/dist/store/user-lock.cjs +1 -2
  426. package/dist/store/user-lock.d.cts +0 -2
  427. package/dist/store/user-lock.d.cts.map +1 -1
  428. package/dist/store/user-lock.d.mts +0 -2
  429. package/dist/store/user-lock.d.mts.map +1 -1
  430. package/dist/store/user-lock.mjs +1 -2
  431. package/dist/templates.cjs +1 -2
  432. package/dist/templates.d.cts +0 -2
  433. package/dist/templates.d.cts.map +1 -1
  434. package/dist/templates.d.mts +0 -2
  435. package/dist/templates.d.mts.map +1 -1
  436. package/dist/templates.mjs +1 -2
  437. package/dist/transports/cloudflare-email.cjs +1 -2
  438. package/dist/transports/cloudflare-email.d.cts +1 -3
  439. package/dist/transports/cloudflare-email.d.cts.map +1 -1
  440. package/dist/transports/cloudflare-email.d.mts +1 -3
  441. package/dist/transports/cloudflare-email.d.mts.map +1 -1
  442. package/dist/transports/cloudflare-email.mjs +1 -2
  443. package/dist/transports/ses.cjs +1 -2
  444. package/dist/transports/ses.d.cts +0 -2
  445. package/dist/transports/ses.d.cts.map +1 -1
  446. package/dist/transports/ses.d.mts +0 -2
  447. package/dist/transports/ses.d.mts.map +1 -1
  448. package/dist/transports/ses.mjs +1 -2
  449. package/dist/transports/sigv4.cjs +1 -2
  450. package/dist/transports/sigv4.d.cts +0 -2
  451. package/dist/transports/sigv4.d.cts.map +1 -1
  452. package/dist/transports/sigv4.d.mts +0 -2
  453. package/dist/transports/sigv4.d.mts.map +1 -1
  454. package/dist/transports/sigv4.mjs +1 -2
  455. package/dist/webhooks.cjs +1 -2
  456. package/dist/webhooks.d.cts +0 -2
  457. package/dist/webhooks.d.cts.map +1 -1
  458. package/dist/webhooks.d.mts +0 -2
  459. package/dist/webhooks.d.mts.map +1 -1
  460. package/dist/webhooks.mjs +1 -2
  461. package/dist/webpush.cjs +1 -2
  462. package/dist/webpush.d.cts +0 -2
  463. package/dist/webpush.d.cts.map +1 -1
  464. package/dist/webpush.d.mts +0 -2
  465. package/dist/webpush.d.mts.map +1 -1
  466. package/dist/webpush.mjs +1 -2
  467. package/package.json +5 -7
  468. package/dist/cloudflare/d1-env.cjs +0 -17
  469. package/dist/cloudflare/d1-env.cjs.map +0 -1
  470. package/dist/cloudflare/d1-env.d.cts +0 -12
  471. package/dist/cloudflare/d1-env.d.cts.map +0 -1
  472. package/dist/cloudflare/d1-env.d.mts +0 -12
  473. package/dist/cloudflare/d1-env.d.mts.map +0 -1
  474. package/dist/cloudflare/d1-env.mjs +0 -16
  475. package/dist/cloudflare/d1-env.mjs.map +0 -1
  476. package/dist/cloudflare/schema.sql +0 -148
  477. package/dist/store/d1.cjs +0 -245
  478. package/dist/store/d1.cjs.map +0 -1
  479. package/dist/store/d1.d.cts +0 -73
  480. package/dist/store/d1.d.cts.map +0 -1
  481. package/dist/store/d1.d.mts +0 -73
  482. package/dist/store/d1.d.mts.map +0 -1
  483. package/dist/store/d1.mjs +0 -244
  484. package/dist/store/d1.mjs.map +0 -1
  485. package/src/cloudflare/schema.sql +0 -148
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.cjs","names":["InstanceNotFoundError"],"sources":["../../src/cloudflare/bindings.ts"],"sourcesContent":["import type { EmailAddress } from '../email';\nimport { InstanceNotFoundError, type WorkflowBindingLike } from '../host/platform';\n\n/**\n * A minimal structural interface over the Cloudflare bindings.\n *\n * @cloudflare/workers-types is deliberately not used: the global types it\n * injects clash with the DOM lib this package's react side needs. A structural\n * subset plus the ambient cloudflare:workers declaration is enough to compile,\n * and the real bindings satisfy it structurally at runtime.\n */\n\n/** Structural subset of D1Result: `meta.changes` is how INSERT OR IGNORE reports whether it inserted. */\nexport interface D1RunResultLike {\n meta?: { changes?: number };\n}\n\nexport interface D1PreparedStatementLike {\n bind(...values: unknown[]): D1PreparedStatementLike;\n first<T = Record<string, unknown>>(): Promise<T | null>;\n all<T = Record<string, unknown>>(): Promise<{ results: T[] }>;\n run(): Promise<D1RunResultLike>;\n}\n\nexport interface D1DatabaseLike {\n prepare(sql: string): D1PreparedStatementLike;\n /** Statements run in order inside one transaction (real D1 semantics) — deploy relies on the atomicity. */\n batch(statements: D1PreparedStatementLike[]): Promise<unknown>;\n}\n\n/**\n * Cloudflare Email Service's send_email binding (structural subset).\n *\n * `idempotencyKey` is part of the call because the send happens inside a\n * `step.do`: a step body re-runs after its fn resolved but before the\n * checkpoint committed, so a binding that drops the key mails the user twice.\n * The binding is app-supplied glue (nothing here can de-duplicate — there is\n * no state between two runs of the same step), which is why the port makes the\n * key impossible to miss rather than merely available.\n */\nexport interface EmailBindingLike {\n send(message: {\n from: EmailAddress;\n to: EmailAddress;\n replyTo?: EmailAddress;\n subject: string;\n html: string;\n /** List-Unsubscribe and List-Unsubscribe-Post, when the email has an unsubscribe link. */\n headers?: Readonly<Record<string, string>>;\n /** `${instanceId}:${nodeId}`: stable across replays and retries — drop a send whose key was already delivered. */\n idempotencyKey: string;\n }): Promise<unknown>;\n}\n\n/** Cloudflare's Workflow binding, as far as the host uses it. */\nexport type CfWorkflowBinding = Pick<WorkflowBindingLike, 'create' | 'get'>;\n\n/** How Cloudflare's `get` reports an unknown instance id. */\nconst CF_NOT_FOUND = 'instance.not_found';\n\n/**\n * The Workflow binding as the host's runtime port: `get` answers an unknown id with\n * `InstanceNotFoundError`, as the port promises, instead of Cloudflare's own error. Everything\n * else is forwarded as is.\n */\nexport function cloudflareJourneyBinding(binding: CfWorkflowBinding): WorkflowBindingLike {\n return {\n create: (options) => binding.create(options),\n async get(id) {\n try {\n return await binding.get(id);\n } catch (error) {\n if (String(error).includes(CF_NOT_FOUND)) {\n throw new InstanceNotFoundError(id, { cause: error });\n }\n throw error;\n }\n },\n };\n}\n\n/**\n * Slack on the deadline when deciding whether a thrown wait was a timeout: the\n * platform may surface the expiry a moment early, and a wait shorter than this\n * has no room to tell the two apart anyway.\n */\nexport const WAKE_TIMEOUT_TOLERANCE_MS = 5_000;\n\n/**\n * Did a wait that threw actually reach its deadline?\n *\n * CF signals a wait timeout by throwing, and so does every other failure in\n * there — a broken binding, an evicted instance, a malformed timeout. Reading\n * them all as timeouts would make an infrastructure fault indistinguishable\n * from \"the user never did it\" (the journey would take its onTimeout branch,\n * early and silently). Only the clock can tell them apart, and only against\n * the absolute deadline: measured from when the wait was parked, a replay\n * after an eviction would start the measure over and read a\n * genuine expiry as a failure.\n */\nexport function wakeExpired(deadlineMs: number, now: number): boolean {\n return now >= deadlineMs - WAKE_TIMEOUT_TOLERANCE_MS;\n}\n"],"mappings":";;;;AA0DA,MAAM,eAAe;;;;;;AAOrB,SAAgB,yBAAyB,SAAiD;CACxF,OAAO;EACL,SAAS,YAAY,QAAQ,OAAO,OAAO;EAC3C,MAAM,IAAI,IAAI;GACZ,IAAI;IACF,OAAO,MAAM,QAAQ,IAAI,EAAE;GAC7B,SAAS,OAAO;IACd,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,YAAY,GACrC,MAAM,IAAIA,sBAAAA,sBAAsB,IAAI,EAAE,OAAO,MAAM,CAAC;IAEtD,MAAM;GACR;EACF;CACF;AACF;;;;;;AAOA,MAAa,4BAA4B;;;;;;;;;;;;;AAczC,SAAgB,YAAY,YAAoB,KAAsB;CACpE,OAAO,OAAO,aAAa;AAC7B"}
1
+ {"version":3,"file":"bindings.cjs","names":["InstanceNotFoundError"],"sources":["../../src/cloudflare/bindings.ts"],"sourcesContent":["import type { EmailAddress } from '../email';\nimport { InstanceNotFoundError, type WorkflowBindingLike } from '../host/platform';\n\n/**\n * A minimal structural interface over the Cloudflare bindings.\n *\n * @cloudflare/workers-types is deliberately not used: the global types it\n * injects clash with the DOM lib this package's react side needs. A structural\n * subset plus the ambient cloudflare:workers declaration is enough to compile,\n * and the real bindings satisfy it structurally at runtime.\n */\n\n/**\n * Cloudflare Email Service's send_email binding (structural subset).\n *\n * `idempotencyKey` is part of the call because the send happens inside a\n * `step.do`: a step body re-runs after its fn resolved but before the\n * checkpoint committed, so a binding that drops the key mails the user twice.\n * The binding is app-supplied glue (nothing here can de-duplicate — there is\n * no state between two runs of the same step), which is why the port makes the\n * key impossible to miss rather than merely available.\n */\nexport interface EmailBindingLike {\n send(message: {\n from: EmailAddress;\n to: EmailAddress;\n replyTo?: EmailAddress;\n subject: string;\n html: string;\n /** List-Unsubscribe and List-Unsubscribe-Post, when the email has an unsubscribe link. */\n headers?: Readonly<Record<string, string>>;\n /** `${instanceId}:${nodeId}`: stable across replays and retries — drop a send whose key was already delivered. */\n idempotencyKey: string;\n }): Promise<unknown>;\n}\n\n/** Cloudflare's Workflow binding, as far as the host uses it. */\nexport type CfWorkflowBinding = Pick<WorkflowBindingLike, 'create' | 'get'>;\n\n/** How Cloudflare's `get` reports an unknown instance id. */\nconst CF_NOT_FOUND = 'instance.not_found';\n\n/**\n * The Workflow binding as the host's runtime port: `get` answers an unknown id with\n * `InstanceNotFoundError`, as the port promises, instead of Cloudflare's own error. Everything\n * else is forwarded as is.\n */\nexport function cloudflareJourneyBinding(binding: CfWorkflowBinding): WorkflowBindingLike {\n return {\n create: (options) => binding.create(options),\n async get(id) {\n try {\n return await binding.get(id);\n } catch (error) {\n if (String(error).includes(CF_NOT_FOUND)) {\n throw new InstanceNotFoundError(id, { cause: error });\n }\n throw error;\n }\n },\n };\n}\n\n/**\n * Slack on the deadline when deciding whether a thrown wait was a timeout: the\n * platform may surface the expiry a moment early, and a wait shorter than this\n * has no room to tell the two apart anyway.\n */\nexport const WAKE_TIMEOUT_TOLERANCE_MS = 5_000;\n\n/**\n * Did a wait that threw actually reach its deadline?\n *\n * CF signals a wait timeout by throwing, and so does every other failure in\n * there — a broken binding, an evicted instance, a malformed timeout. Reading\n * them all as timeouts would make an infrastructure fault indistinguishable\n * from \"the user never did it\" (the journey would take its onTimeout branch,\n * early and silently). Only the clock can tell them apart, and only against\n * the absolute deadline: measured from when the wait was parked, a replay\n * after an eviction would start the measure over and read a\n * genuine expiry as a failure.\n */\nexport function wakeExpired(deadlineMs: number, now: number): boolean {\n return now >= deadlineMs - WAKE_TIMEOUT_TOLERANCE_MS;\n}\n"],"mappings":";;;;AAwCA,MAAM,eAAe;;;;;;AAOrB,SAAgB,yBAAyB,SAAiD;CACxF,OAAO;EACL,SAAS,YAAY,QAAQ,OAAO,OAAO;EAC3C,MAAM,IAAI,IAAI;GACZ,IAAI;IACF,OAAO,MAAM,QAAQ,IAAI,EAAE;GAC7B,SAAS,OAAO;IACd,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,YAAY,GACrC,MAAM,IAAIA,sBAAAA,sBAAsB,IAAI,EAAE,OAAO,MAAM,CAAC;IAEtD,MAAM;GACR;EACF;CACF;AACF;;;;;;AAOA,MAAa,4BAA4B;;;;;;;;;;;;;AAczC,SAAgB,YAAY,YAAoB,KAAsB;CACpE,OAAO,OAAO,aAAa;AAC7B"}
@@ -1,6 +1,5 @@
1
1
  import { EmailAddress } from "../email.cjs";
2
2
  import { WorkflowBindingLike } from "../host/platform.cjs";
3
- //#region src/cloudflare/bindings.d.ts
4
3
  /**
5
4
  * A minimal structural interface over the Cloudflare bindings.
6
5
  *
@@ -9,25 +8,6 @@ import { WorkflowBindingLike } from "../host/platform.cjs";
9
8
  * subset plus the ambient cloudflare:workers declaration is enough to compile,
10
9
  * and the real bindings satisfy it structurally at runtime.
11
10
  */
12
- /** Structural subset of D1Result: `meta.changes` is how INSERT OR IGNORE reports whether it inserted. */
13
- export interface D1RunResultLike {
14
- meta?: {
15
- changes?: number;
16
- };
17
- }
18
- export interface D1PreparedStatementLike {
19
- bind(...values: unknown[]): D1PreparedStatementLike;
20
- first<T = Record<string, unknown>>(): Promise<T | null>;
21
- all<T = Record<string, unknown>>(): Promise<{
22
- results: T[];
23
- }>;
24
- run(): Promise<D1RunResultLike>;
25
- }
26
- export interface D1DatabaseLike {
27
- prepare(sql: string): D1PreparedStatementLike;
28
- /** Statements run in order inside one transaction (real D1 semantics) — deploy relies on the atomicity. */
29
- batch(statements: D1PreparedStatementLike[]): Promise<unknown>;
30
- }
31
11
  /**
32
12
  * Cloudflare Email Service's send_email binding (structural subset).
33
13
  *
@@ -78,5 +58,4 @@ export declare const WAKE_TIMEOUT_TOLERANCE_MS = 5000;
78
58
  * genuine expiry as a failure.
79
59
  */
80
60
  export declare function wakeExpired(deadlineMs: number, now: number): boolean;
81
- //#endregion
82
61
  //# sourceMappingURL=bindings.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.d.cts","names":[],"sources":["../../src/cloudflare/bindings.ts"],"mappings":";;;;;;;;;;;;iBAaiB;EACf;IAAS;;;iBAGM;EACf,QAAQ,oBAAoB;EAC5B,MAAM,IAAI,4BAA4B,QAAQ;EAC9C,IAAI,IAAI,4BAA4B;IAAU,SAAS;;EACvD,OAAO,QAAQ;;iBAGA;EACf,QAAQ,cAAc;;EAEtB,MAAM,YAAY,4BAA4B;;;;;;;;;;;;iBAa/B;EACf,KAAK;IACH,MAAM;IACN,IAAI;IACJ,UAAU;IACV;IACA;;IAEA,UAAU,SAAS;;IAEnB;MACE;;;YAIM,oBAAoB,KAAK;;;;;;wBAUrB,yBAAyB,SAAS,oBAAoB;;;;;;qBAqBzD;;;;;;;;;;;;;wBAcG,YAAY,oBAAoB"}
1
+ {"version":3,"file":"bindings.d.cts","names":[],"sources":["../../src/cloudflare/bindings.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAsBiB;EACf,KAAK;IACH,MAAM;IACN,IAAI;IACJ,UAAU;IACV;IACA;;IAEA,UAAU,SAAS;;IAEnB;MACE;;;YAIM,oBAAoB,KAAK;;;;;;wBAUrB,yBAAyB,SAAS,oBAAoB;;;;;;qBAqBzD;;;;;;;;;;;;;wBAcG,YAAY,oBAAoB"}
@@ -1,6 +1,5 @@
1
1
  import { EmailAddress } from "../email.mjs";
2
2
  import { WorkflowBindingLike } from "../host/platform.mjs";
3
- //#region src/cloudflare/bindings.d.ts
4
3
  /**
5
4
  * A minimal structural interface over the Cloudflare bindings.
6
5
  *
@@ -9,25 +8,6 @@ import { WorkflowBindingLike } from "../host/platform.mjs";
9
8
  * subset plus the ambient cloudflare:workers declaration is enough to compile,
10
9
  * and the real bindings satisfy it structurally at runtime.
11
10
  */
12
- /** Structural subset of D1Result: `meta.changes` is how INSERT OR IGNORE reports whether it inserted. */
13
- export interface D1RunResultLike {
14
- meta?: {
15
- changes?: number;
16
- };
17
- }
18
- export interface D1PreparedStatementLike {
19
- bind(...values: unknown[]): D1PreparedStatementLike;
20
- first<T = Record<string, unknown>>(): Promise<T | null>;
21
- all<T = Record<string, unknown>>(): Promise<{
22
- results: T[];
23
- }>;
24
- run(): Promise<D1RunResultLike>;
25
- }
26
- export interface D1DatabaseLike {
27
- prepare(sql: string): D1PreparedStatementLike;
28
- /** Statements run in order inside one transaction (real D1 semantics) — deploy relies on the atomicity. */
29
- batch(statements: D1PreparedStatementLike[]): Promise<unknown>;
30
- }
31
11
  /**
32
12
  * Cloudflare Email Service's send_email binding (structural subset).
33
13
  *
@@ -78,5 +58,4 @@ export declare const WAKE_TIMEOUT_TOLERANCE_MS = 5000;
78
58
  * genuine expiry as a failure.
79
59
  */
80
60
  export declare function wakeExpired(deadlineMs: number, now: number): boolean;
81
- //#endregion
82
61
  //# sourceMappingURL=bindings.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.d.mts","names":[],"sources":["../../src/cloudflare/bindings.ts"],"mappings":";;;;;;;;;;;;iBAaiB;EACf;IAAS;;;iBAGM;EACf,QAAQ,oBAAoB;EAC5B,MAAM,IAAI,4BAA4B,QAAQ;EAC9C,IAAI,IAAI,4BAA4B;IAAU,SAAS;;EACvD,OAAO,QAAQ;;iBAGA;EACf,QAAQ,cAAc;;EAEtB,MAAM,YAAY,4BAA4B;;;;;;;;;;;;iBAa/B;EACf,KAAK;IACH,MAAM;IACN,IAAI;IACJ,UAAU;IACV;IACA;;IAEA,UAAU,SAAS;;IAEnB;MACE;;;YAIM,oBAAoB,KAAK;;;;;;wBAUrB,yBAAyB,SAAS,oBAAoB;;;;;;qBAqBzD;;;;;;;;;;;;;wBAcG,YAAY,oBAAoB"}
1
+ {"version":3,"file":"bindings.d.mts","names":[],"sources":["../../src/cloudflare/bindings.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAsBiB;EACf,KAAK;IACH,MAAM;IACN,IAAI;IACJ,UAAU;IACV;IACA;;IAEA,UAAU,SAAS;;IAEnB;MACE;;;YAIM,oBAAoB,KAAK;;;;;;wBAUrB,yBAAyB,SAAS,oBAAoB;;;;;;qBAqBzD;;;;;;;;;;;;;wBAcG,YAAY,oBAAoB"}
@@ -1,5 +1,5 @@
1
1
  import { InstanceNotFoundError } from "../host/platform.mjs";
2
- //#region src/cloudflare/bindings.ts
2
+ // src/cloudflare/bindings.ts
3
3
  /** How Cloudflare's `get` reports an unknown instance id. */
4
4
  const CF_NOT_FOUND = "instance.not_found";
5
5
  /**
@@ -41,7 +41,6 @@ const WAKE_TIMEOUT_TOLERANCE_MS = 5e3;
41
41
  function wakeExpired(deadlineMs, now) {
42
42
  return now >= deadlineMs - WAKE_TIMEOUT_TOLERANCE_MS;
43
43
  }
44
- //#endregion
45
44
  export { WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired };
46
45
 
47
46
  //# sourceMappingURL=bindings.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.mjs","names":[],"sources":["../../src/cloudflare/bindings.ts"],"sourcesContent":["import type { EmailAddress } from '../email';\nimport { InstanceNotFoundError, type WorkflowBindingLike } from '../host/platform';\n\n/**\n * A minimal structural interface over the Cloudflare bindings.\n *\n * @cloudflare/workers-types is deliberately not used: the global types it\n * injects clash with the DOM lib this package's react side needs. A structural\n * subset plus the ambient cloudflare:workers declaration is enough to compile,\n * and the real bindings satisfy it structurally at runtime.\n */\n\n/** Structural subset of D1Result: `meta.changes` is how INSERT OR IGNORE reports whether it inserted. */\nexport interface D1RunResultLike {\n meta?: { changes?: number };\n}\n\nexport interface D1PreparedStatementLike {\n bind(...values: unknown[]): D1PreparedStatementLike;\n first<T = Record<string, unknown>>(): Promise<T | null>;\n all<T = Record<string, unknown>>(): Promise<{ results: T[] }>;\n run(): Promise<D1RunResultLike>;\n}\n\nexport interface D1DatabaseLike {\n prepare(sql: string): D1PreparedStatementLike;\n /** Statements run in order inside one transaction (real D1 semantics) — deploy relies on the atomicity. */\n batch(statements: D1PreparedStatementLike[]): Promise<unknown>;\n}\n\n/**\n * Cloudflare Email Service's send_email binding (structural subset).\n *\n * `idempotencyKey` is part of the call because the send happens inside a\n * `step.do`: a step body re-runs after its fn resolved but before the\n * checkpoint committed, so a binding that drops the key mails the user twice.\n * The binding is app-supplied glue (nothing here can de-duplicate — there is\n * no state between two runs of the same step), which is why the port makes the\n * key impossible to miss rather than merely available.\n */\nexport interface EmailBindingLike {\n send(message: {\n from: EmailAddress;\n to: EmailAddress;\n replyTo?: EmailAddress;\n subject: string;\n html: string;\n /** List-Unsubscribe and List-Unsubscribe-Post, when the email has an unsubscribe link. */\n headers?: Readonly<Record<string, string>>;\n /** `${instanceId}:${nodeId}`: stable across replays and retries — drop a send whose key was already delivered. */\n idempotencyKey: string;\n }): Promise<unknown>;\n}\n\n/** Cloudflare's Workflow binding, as far as the host uses it. */\nexport type CfWorkflowBinding = Pick<WorkflowBindingLike, 'create' | 'get'>;\n\n/** How Cloudflare's `get` reports an unknown instance id. */\nconst CF_NOT_FOUND = 'instance.not_found';\n\n/**\n * The Workflow binding as the host's runtime port: `get` answers an unknown id with\n * `InstanceNotFoundError`, as the port promises, instead of Cloudflare's own error. Everything\n * else is forwarded as is.\n */\nexport function cloudflareJourneyBinding(binding: CfWorkflowBinding): WorkflowBindingLike {\n return {\n create: (options) => binding.create(options),\n async get(id) {\n try {\n return await binding.get(id);\n } catch (error) {\n if (String(error).includes(CF_NOT_FOUND)) {\n throw new InstanceNotFoundError(id, { cause: error });\n }\n throw error;\n }\n },\n };\n}\n\n/**\n * Slack on the deadline when deciding whether a thrown wait was a timeout: the\n * platform may surface the expiry a moment early, and a wait shorter than this\n * has no room to tell the two apart anyway.\n */\nexport const WAKE_TIMEOUT_TOLERANCE_MS = 5_000;\n\n/**\n * Did a wait that threw actually reach its deadline?\n *\n * CF signals a wait timeout by throwing, and so does every other failure in\n * there — a broken binding, an evicted instance, a malformed timeout. Reading\n * them all as timeouts would make an infrastructure fault indistinguishable\n * from \"the user never did it\" (the journey would take its onTimeout branch,\n * early and silently). Only the clock can tell them apart, and only against\n * the absolute deadline: measured from when the wait was parked, a replay\n * after an eviction would start the measure over and read a\n * genuine expiry as a failure.\n */\nexport function wakeExpired(deadlineMs: number, now: number): boolean {\n return now >= deadlineMs - WAKE_TIMEOUT_TOLERANCE_MS;\n}\n"],"mappings":";;;AA0DA,MAAM,eAAe;;;;;;AAOrB,SAAgB,yBAAyB,SAAiD;CACxF,OAAO;EACL,SAAS,YAAY,QAAQ,OAAO,OAAO;EAC3C,MAAM,IAAI,IAAI;GACZ,IAAI;IACF,OAAO,MAAM,QAAQ,IAAI,EAAE;GAC7B,SAAS,OAAO;IACd,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,YAAY,GACrC,MAAM,IAAI,sBAAsB,IAAI,EAAE,OAAO,MAAM,CAAC;IAEtD,MAAM;GACR;EACF;CACF;AACF;;;;;;AAOA,MAAa,4BAA4B;;;;;;;;;;;;;AAczC,SAAgB,YAAY,YAAoB,KAAsB;CACpE,OAAO,OAAO,aAAa;AAC7B"}
1
+ {"version":3,"file":"bindings.mjs","names":[],"sources":["../../src/cloudflare/bindings.ts"],"sourcesContent":["import type { EmailAddress } from '../email';\nimport { InstanceNotFoundError, type WorkflowBindingLike } from '../host/platform';\n\n/**\n * A minimal structural interface over the Cloudflare bindings.\n *\n * @cloudflare/workers-types is deliberately not used: the global types it\n * injects clash with the DOM lib this package's react side needs. A structural\n * subset plus the ambient cloudflare:workers declaration is enough to compile,\n * and the real bindings satisfy it structurally at runtime.\n */\n\n/**\n * Cloudflare Email Service's send_email binding (structural subset).\n *\n * `idempotencyKey` is part of the call because the send happens inside a\n * `step.do`: a step body re-runs after its fn resolved but before the\n * checkpoint committed, so a binding that drops the key mails the user twice.\n * The binding is app-supplied glue (nothing here can de-duplicate — there is\n * no state between two runs of the same step), which is why the port makes the\n * key impossible to miss rather than merely available.\n */\nexport interface EmailBindingLike {\n send(message: {\n from: EmailAddress;\n to: EmailAddress;\n replyTo?: EmailAddress;\n subject: string;\n html: string;\n /** List-Unsubscribe and List-Unsubscribe-Post, when the email has an unsubscribe link. */\n headers?: Readonly<Record<string, string>>;\n /** `${instanceId}:${nodeId}`: stable across replays and retries — drop a send whose key was already delivered. */\n idempotencyKey: string;\n }): Promise<unknown>;\n}\n\n/** Cloudflare's Workflow binding, as far as the host uses it. */\nexport type CfWorkflowBinding = Pick<WorkflowBindingLike, 'create' | 'get'>;\n\n/** How Cloudflare's `get` reports an unknown instance id. */\nconst CF_NOT_FOUND = 'instance.not_found';\n\n/**\n * The Workflow binding as the host's runtime port: `get` answers an unknown id with\n * `InstanceNotFoundError`, as the port promises, instead of Cloudflare's own error. Everything\n * else is forwarded as is.\n */\nexport function cloudflareJourneyBinding(binding: CfWorkflowBinding): WorkflowBindingLike {\n return {\n create: (options) => binding.create(options),\n async get(id) {\n try {\n return await binding.get(id);\n } catch (error) {\n if (String(error).includes(CF_NOT_FOUND)) {\n throw new InstanceNotFoundError(id, { cause: error });\n }\n throw error;\n }\n },\n };\n}\n\n/**\n * Slack on the deadline when deciding whether a thrown wait was a timeout: the\n * platform may surface the expiry a moment early, and a wait shorter than this\n * has no room to tell the two apart anyway.\n */\nexport const WAKE_TIMEOUT_TOLERANCE_MS = 5_000;\n\n/**\n * Did a wait that threw actually reach its deadline?\n *\n * CF signals a wait timeout by throwing, and so does every other failure in\n * there — a broken binding, an evicted instance, a malformed timeout. Reading\n * them all as timeouts would make an infrastructure fault indistinguishable\n * from \"the user never did it\" (the journey would take its onTimeout branch,\n * early and silently). Only the clock can tell them apart, and only against\n * the absolute deadline: measured from when the wait was parked, a replay\n * after an eviction would start the measure over and read a\n * genuine expiry as a failure.\n */\nexport function wakeExpired(deadlineMs: number, now: number): boolean {\n return now >= deadlineMs - WAKE_TIMEOUT_TOLERANCE_MS;\n}\n"],"mappings":";;;AAwCA,MAAM,eAAe;;;;;;AAOrB,SAAgB,yBAAyB,SAAiD;CACxF,OAAO;EACL,SAAS,YAAY,QAAQ,OAAO,OAAO;EAC3C,MAAM,IAAI,IAAI;GACZ,IAAI;IACF,OAAO,MAAM,QAAQ,IAAI,EAAE;GAC7B,SAAS,OAAO;IACd,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,YAAY,GACrC,MAAM,IAAI,sBAAsB,IAAI,EAAE,OAAO,MAAM,CAAC;IAEtD,MAAM;GACR;EACF;CACF;AACF;;;;;;AAOA,MAAa,4BAA4B;;;;;;;;;;;;;AAczC,SAAgB,YAAY,YAAoB,KAAsB;CACpE,OAAO,OAAO,aAAa;AAC7B"}
@@ -4,8 +4,6 @@ const require_store_erasure = require("../store/erasure.cjs");
4
4
  const require_store_postgres_reporting = require("../store/postgres-reporting.cjs");
5
5
  const require_store_postgres = require("../store/postgres.cjs");
6
6
  const require_store_facts = require("../store/facts.cjs");
7
- const require_store_d1 = require("../store/d1.cjs");
8
- const require_cloudflare_d1_env = require("./d1-env.cjs");
9
7
  const require_store_index = require("../store/index.cjs");
10
8
  const require_host_platform = require("../host/platform.cjs");
11
9
  const require_host_ingest = require("../host/ingest.cjs");
@@ -22,7 +20,6 @@ const require_cloudflare_runner = require("./runner.cjs");
22
20
  const require_cloudflare_worker = require("./worker.cjs");
23
21
  exports.BURST_WINDOW_MS = require_reporting_classify.BURST_WINDOW_MS;
24
22
  exports.BundleIntegrityError = require_host_ingest.BundleIntegrityError;
25
- exports.D1JourneyStore = require_store_d1.D1JourneyStore;
26
23
  exports.DEFAULT_QUICK_MS = require_reporting_classify.DEFAULT_QUICK_MS;
27
24
  exports.EmailSender = require_email_sender.EmailSender;
28
25
  exports.EnvValidationError = require_host_journey_host.EnvValidationError;
@@ -34,7 +31,6 @@ exports.PostgresJourneyStore = require_store_postgres.PostgresJourneyStore;
34
31
  exports.PostgresReporting = require_store_postgres_reporting.PostgresReporting;
35
32
  exports.SWEEP_PAGE_SIZE = require_host_ingest.SWEEP_PAGE_SIZE;
36
33
  exports.SchemaMismatchError = require_store_index.SchemaMismatchError;
37
- exports.UnversionedStoreError = require_host_ingest.UnversionedStoreError;
38
34
  exports.UserErasedError = require_store_erasure.UserErasedError;
39
35
  exports.WAKE_EVENT_TYPE = require_host_platform.WAKE_EVENT_TYPE;
40
36
  exports.WAKE_TIMEOUT_TOLERANCE_MS = require_cloudflare_bindings.WAKE_TIMEOUT_TOLERANCE_MS;
@@ -45,7 +41,6 @@ exports.channelsFromConfig = require_host_channels.channelsFromConfig;
45
41
  exports.classifyClick = require_reporting_classify.classifyClick;
46
42
  exports.classifyOpen = require_reporting_classify.classifyOpen;
47
43
  exports.cloudflareJourneyBinding = require_cloudflare_bindings.cloudflareJourneyBinding;
48
- exports.d1Store = require_cloudflare_d1_env.d1Store;
49
44
  exports.deployBundle = require_host_ingest.deployBundle;
50
45
  exports.forgetUser = require_host_ingest.forgetUser;
51
46
  exports.handleRequest = require_host_http.handleRequest;
@@ -1,9 +1,6 @@
1
1
  import { JourneyObserver, LinkPurpose, MessageTracking, OutboundMessage, PushDevice, SendResult } from "../engine/ports.cjs";
2
2
  import { EmailAddress } from "../email.cjs";
3
3
  import { UserErasedError } from "../store/erasure.cjs";
4
- import { InstanceNotFoundError, JourneyEnv, JourneyParams, WAKE_EVENT_TYPE, WorkflowBindingLike, WorkflowInstanceLike } from "../host/platform.cjs";
5
- import { D1DatabaseLike, EmailBindingLike, WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired } from "./bindings.cjs";
6
- import { D1JourneyStore } from "../store/d1.cjs";
7
4
  import { JourneyFactSource } from "../store/facts.cjs";
8
5
  import { SqlClientLike } from "../store/sql.cjs";
9
6
  import { PostgresJourneyStore, PostgresJourneyStoreOptions } from "../store/postgres.cjs";
@@ -11,9 +8,10 @@ import { PostgresReporting } from "../store/postgres-reporting.cjs";
11
8
  import { BundleVersion, Engagement, EntryInput, EntryOutcome, EventInput, JourneyReporting, JourneyStore, MessageRecord, ProfileProps, SchemaMismatchError, SegmentTriggerRoute, StoreLease, TriggerRoute } from "../store/index.cjs";
12
9
  import { EmailMessage, EmailRenderer, EmailSender, EmailSenderOptions, EmailTransport, RenderedEmail, trackEmail } from "../email-sender.cjs";
13
10
  import { Authorize, authorized, bearerMatches, timingSafeEqual } from "../host/auth.cjs";
14
- import { BundleIntegrityError, DeployResult, DeviceRegistration, IdentifyResult, IngestInput, IngestResult, SWEEP_PAGE_SIZE, SweepPage, SweepResult, UnversionedStoreError, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.cjs";
11
+ import { EmailBindingLike, WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired } from "./bindings.cjs";
12
+ import { InstanceNotFoundError, JourneyEnv, JourneyParams, WAKE_EVENT_TYPE, WorkflowBindingLike, WorkflowInstanceLike } from "../host/platform.cjs";
13
+ import { BundleIntegrityError, DeployResult, DeviceRegistration, IdentifyResult, IngestInput, IngestResult, SWEEP_PAGE_SIZE, SweepPage, SweepResult, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.cjs";
15
14
  import { EnvValidationError } from "../host/journey-host.cjs";
16
- import { d1Store } from "./d1-env.cjs";
17
15
  import { TrackingOptions, handleTracking, recordPushOpen } from "../reporting/tracking.cjs";
18
16
  import { IngestValidation, handleRequest } from "../host/http.cjs";
19
17
  import { JourneyRunner } from "./runner.cjs";
@@ -22,4 +20,4 @@ import { ChannelsConfig, channelsFromConfig, journeyMode, runtimeFromConfig } fr
22
20
  import { reportingObserver } from "../reporting/observer.cjs";
23
21
  import { BURST_WINDOW_MS, ClassifyOptions, ClickFacts, DEFAULT_QUICK_MS, RequestFacts, Verdict, classifyClick, classifyOpen } from "../reporting/classify.cjs";
24
22
  import { ExecutionContextLike, JourneyWorker, JourneyWorkerOptions, journeyWorker } from "./worker.cjs";
25
- export { type Authorize, BURST_WINDOW_MS, BundleIntegrityError, type BundleVersion, type ChannelsConfig, type ClassifyOptions, type ClickFacts, type D1DatabaseLike, D1JourneyStore, DEFAULT_QUICK_MS, type DeployResult, type DeviceRegistration, type EmailAddress, type EmailBindingLike, type EmailMessage, type EmailRenderer, EmailSender, type EmailSenderOptions, type EmailTransport, type Engagement, type EntryInput, type EntryOutcome, EnvValidationError, type EventInput, type ExecutionContextLike, type IdentifyResult, type IngestInput, type IngestResult, type IngestValidation, InstanceNotFoundError, type JourneyEnv, JourneyFactSource, type JourneyObserver, type JourneyParams, type JourneyReporting, JourneyRunner, type JourneyStore, type JourneyWorker, type JourneyWorkerOptions, type LinkPurpose, LogMessageSender, type MessageRecord, type MessageTracking, type OutboundMessage, PostgresJourneyStore, type PostgresJourneyStoreOptions, PostgresReporting, type ProfileProps, type PushDevice, type RenderedEmail, type RequestFacts, SWEEP_PAGE_SIZE, SchemaMismatchError, type SegmentTriggerRoute, type SendResult, type SqlClientLike, type StoreLease, type SweepPage, type SweepResult, type TrackingOptions, type TriggerRoute, UnversionedStoreError, UserErasedError, type Verdict, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, type WorkflowBindingLike, type WorkflowInstanceLike, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, d1Store, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
23
+ export { type Authorize, BURST_WINDOW_MS, BundleIntegrityError, type BundleVersion, type ChannelsConfig, type ClassifyOptions, type ClickFacts, DEFAULT_QUICK_MS, type DeployResult, type DeviceRegistration, type EmailAddress, type EmailBindingLike, type EmailMessage, type EmailRenderer, EmailSender, type EmailSenderOptions, type EmailTransport, type Engagement, type EntryInput, type EntryOutcome, EnvValidationError, type EventInput, type ExecutionContextLike, type IdentifyResult, type IngestInput, type IngestResult, type IngestValidation, InstanceNotFoundError, type JourneyEnv, JourneyFactSource, type JourneyObserver, type JourneyParams, type JourneyReporting, JourneyRunner, type JourneyStore, type JourneyWorker, type JourneyWorkerOptions, type LinkPurpose, LogMessageSender, type MessageRecord, type MessageTracking, type OutboundMessage, PostgresJourneyStore, type PostgresJourneyStoreOptions, PostgresReporting, type ProfileProps, type PushDevice, type RenderedEmail, type RequestFacts, SWEEP_PAGE_SIZE, SchemaMismatchError, type SegmentTriggerRoute, type SendResult, type SqlClientLike, type StoreLease, type SweepPage, type SweepResult, type TrackingOptions, type TriggerRoute, UserErasedError, type Verdict, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, type WorkflowBindingLike, type WorkflowInstanceLike, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
@@ -1,9 +1,6 @@
1
1
  import { JourneyObserver, LinkPurpose, MessageTracking, OutboundMessage, PushDevice, SendResult } from "../engine/ports.mjs";
2
2
  import { EmailAddress } from "../email.mjs";
3
3
  import { UserErasedError } from "../store/erasure.mjs";
4
- import { InstanceNotFoundError, JourneyEnv, JourneyParams, WAKE_EVENT_TYPE, WorkflowBindingLike, WorkflowInstanceLike } from "../host/platform.mjs";
5
- import { D1DatabaseLike, EmailBindingLike, WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired } from "./bindings.mjs";
6
- import { D1JourneyStore } from "../store/d1.mjs";
7
4
  import { JourneyFactSource } from "../store/facts.mjs";
8
5
  import { SqlClientLike } from "../store/sql.mjs";
9
6
  import { PostgresJourneyStore, PostgresJourneyStoreOptions } from "../store/postgres.mjs";
@@ -11,9 +8,10 @@ import { PostgresReporting } from "../store/postgres-reporting.mjs";
11
8
  import { BundleVersion, Engagement, EntryInput, EntryOutcome, EventInput, JourneyReporting, JourneyStore, MessageRecord, ProfileProps, SchemaMismatchError, SegmentTriggerRoute, StoreLease, TriggerRoute } from "../store/index.mjs";
12
9
  import { EmailMessage, EmailRenderer, EmailSender, EmailSenderOptions, EmailTransport, RenderedEmail, trackEmail } from "../email-sender.mjs";
13
10
  import { Authorize, authorized, bearerMatches, timingSafeEqual } from "../host/auth.mjs";
14
- import { BundleIntegrityError, DeployResult, DeviceRegistration, IdentifyResult, IngestInput, IngestResult, SWEEP_PAGE_SIZE, SweepPage, SweepResult, UnversionedStoreError, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.mjs";
11
+ import { EmailBindingLike, WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired } from "./bindings.mjs";
12
+ import { InstanceNotFoundError, JourneyEnv, JourneyParams, WAKE_EVENT_TYPE, WorkflowBindingLike, WorkflowInstanceLike } from "../host/platform.mjs";
13
+ import { BundleIntegrityError, DeployResult, DeviceRegistration, IdentifyResult, IngestInput, IngestResult, SWEEP_PAGE_SIZE, SweepPage, SweepResult, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.mjs";
15
14
  import { EnvValidationError } from "../host/journey-host.mjs";
16
- import { d1Store } from "./d1-env.mjs";
17
15
  import { TrackingOptions, handleTracking, recordPushOpen } from "../reporting/tracking.mjs";
18
16
  import { IngestValidation, handleRequest } from "../host/http.mjs";
19
17
  import { JourneyRunner } from "./runner.mjs";
@@ -22,4 +20,4 @@ import { ChannelsConfig, channelsFromConfig, journeyMode, runtimeFromConfig } fr
22
20
  import { reportingObserver } from "../reporting/observer.mjs";
23
21
  import { BURST_WINDOW_MS, ClassifyOptions, ClickFacts, DEFAULT_QUICK_MS, RequestFacts, Verdict, classifyClick, classifyOpen } from "../reporting/classify.mjs";
24
22
  import { ExecutionContextLike, JourneyWorker, JourneyWorkerOptions, journeyWorker } from "./worker.mjs";
25
- export { type Authorize, BURST_WINDOW_MS, BundleIntegrityError, type BundleVersion, type ChannelsConfig, type ClassifyOptions, type ClickFacts, type D1DatabaseLike, D1JourneyStore, DEFAULT_QUICK_MS, type DeployResult, type DeviceRegistration, type EmailAddress, type EmailBindingLike, type EmailMessage, type EmailRenderer, EmailSender, type EmailSenderOptions, type EmailTransport, type Engagement, type EntryInput, type EntryOutcome, EnvValidationError, type EventInput, type ExecutionContextLike, type IdentifyResult, type IngestInput, type IngestResult, type IngestValidation, InstanceNotFoundError, type JourneyEnv, JourneyFactSource, type JourneyObserver, type JourneyParams, type JourneyReporting, JourneyRunner, type JourneyStore, type JourneyWorker, type JourneyWorkerOptions, type LinkPurpose, LogMessageSender, type MessageRecord, type MessageTracking, type OutboundMessage, PostgresJourneyStore, type PostgresJourneyStoreOptions, PostgresReporting, type ProfileProps, type PushDevice, type RenderedEmail, type RequestFacts, SWEEP_PAGE_SIZE, SchemaMismatchError, type SegmentTriggerRoute, type SendResult, type SqlClientLike, type StoreLease, type SweepPage, type SweepResult, type TrackingOptions, type TriggerRoute, UnversionedStoreError, UserErasedError, type Verdict, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, type WorkflowBindingLike, type WorkflowInstanceLike, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, d1Store, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
23
+ export { type Authorize, BURST_WINDOW_MS, BundleIntegrityError, type BundleVersion, type ChannelsConfig, type ClassifyOptions, type ClickFacts, DEFAULT_QUICK_MS, type DeployResult, type DeviceRegistration, type EmailAddress, type EmailBindingLike, type EmailMessage, type EmailRenderer, EmailSender, type EmailSenderOptions, type EmailTransport, type Engagement, type EntryInput, type EntryOutcome, EnvValidationError, type EventInput, type ExecutionContextLike, type IdentifyResult, type IngestInput, type IngestResult, type IngestValidation, InstanceNotFoundError, type JourneyEnv, JourneyFactSource, type JourneyObserver, type JourneyParams, type JourneyReporting, JourneyRunner, type JourneyStore, type JourneyWorker, type JourneyWorkerOptions, type LinkPurpose, LogMessageSender, type MessageRecord, type MessageTracking, type OutboundMessage, PostgresJourneyStore, type PostgresJourneyStoreOptions, PostgresReporting, type ProfileProps, type PushDevice, type RenderedEmail, type RequestFacts, SWEEP_PAGE_SIZE, SchemaMismatchError, type SegmentTriggerRoute, type SendResult, type SqlClientLike, type StoreLease, type SweepPage, type SweepResult, type TrackingOptions, type TriggerRoute, UserErasedError, type Verdict, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, type WorkflowBindingLike, type WorkflowInstanceLike, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
@@ -3,11 +3,9 @@ import { UserErasedError } from "../store/erasure.mjs";
3
3
  import { PostgresReporting } from "../store/postgres-reporting.mjs";
4
4
  import { PostgresJourneyStore } from "../store/postgres.mjs";
5
5
  import { JourneyFactSource } from "../store/facts.mjs";
6
- import { D1JourneyStore } from "../store/d1.mjs";
7
- import { d1Store } from "./d1-env.mjs";
8
6
  import { SchemaMismatchError } from "../store/index.mjs";
9
7
  import { InstanceNotFoundError, WAKE_EVENT_TYPE } from "../host/platform.mjs";
10
- import { BundleIntegrityError, SWEEP_PAGE_SIZE, UnversionedStoreError, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.mjs";
8
+ import { BundleIntegrityError, SWEEP_PAGE_SIZE, deployBundle, forgetUser, identifyUser, ingestEvent, registerDevice, removeDevice, sweepMaintenance, sweepSegments, sweepSegmentsPaged, unbindDevice } from "../host/ingest.mjs";
11
9
  import { reportingObserver } from "../reporting/observer.mjs";
12
10
  import { LogMessageSender, WebhookMessageSender, routeByChannel, routeByPlatform } from "../host/senders.mjs";
13
11
  import { channelsFromConfig, journeyMode, runtimeFromConfig } from "../host/channels.mjs";
@@ -19,4 +17,4 @@ import { EnvValidationError } from "../host/journey-host.mjs";
19
17
  import { WAKE_TIMEOUT_TOLERANCE_MS, cloudflareJourneyBinding, wakeExpired } from "./bindings.mjs";
20
18
  import { JourneyRunner } from "./runner.mjs";
21
19
  import { journeyWorker } from "./worker.mjs";
22
- export { BURST_WINDOW_MS, BundleIntegrityError, D1JourneyStore, DEFAULT_QUICK_MS, EmailSender, EnvValidationError, InstanceNotFoundError, JourneyFactSource, JourneyRunner, LogMessageSender, PostgresJourneyStore, PostgresReporting, SWEEP_PAGE_SIZE, SchemaMismatchError, UnversionedStoreError, UserErasedError, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, d1Store, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
20
+ export { BURST_WINDOW_MS, BundleIntegrityError, DEFAULT_QUICK_MS, EmailSender, EnvValidationError, InstanceNotFoundError, JourneyFactSource, JourneyRunner, LogMessageSender, PostgresJourneyStore, PostgresReporting, SWEEP_PAGE_SIZE, SchemaMismatchError, UserErasedError, WAKE_EVENT_TYPE, WAKE_TIMEOUT_TOLERANCE_MS, WebhookMessageSender, authorized, bearerMatches, channelsFromConfig, classifyClick, classifyOpen, cloudflareJourneyBinding, deployBundle, forgetUser, handleRequest, handleTracking, identifyUser, ingestEvent, journeyMode, journeyWorker, recordPushOpen, registerDevice, removeDevice, reportingObserver, routeByChannel, routeByPlatform, runtimeFromConfig, sweepMaintenance, sweepSegments, sweepSegmentsPaged, timingSafeEqual, trackEmail, unbindDevice, wakeExpired };
@@ -1,7 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_engine_retry = require("../engine/retry.cjs");
3
3
  const require_runtime = require("../runtime.cjs");
4
- const require_cloudflare_d1_env = require("./d1-env.cjs");
5
4
  const require_host_platform = require("../host/platform.cjs");
6
5
  const require_host_execute = require("../host/execute.cjs");
7
6
  const require_engine_actions = require("../engine/actions.cjs");
@@ -9,7 +8,7 @@ const require_host_senders = require("../host/senders.cjs");
9
8
  const require_cloudflare_bindings = require("./bindings.cjs");
10
9
  let cloudflare_workers = require("cloudflare:workers");
11
10
  let cloudflare_workflows = require("cloudflare:workflows");
12
- //#region src/cloudflare/runner.ts
11
+ // src/cloudflare/runner.ts
13
12
  /**
14
13
  * Adapts CF's WorkflowStep to EngineStep.
15
14
  * subscribe/unsubscribe write the subscription table inside durable steps (the
@@ -79,13 +78,13 @@ var CfEngineStep = class {
79
78
  */
80
79
  var JourneyRunner = class extends cloudflare_workers.WorkflowEntrypoint {
81
80
  /**
82
- * The data plane. D1 from the env by default; an app on Postgres
83
- * overrides this (and `closeStore` if its client needs closing):
81
+ * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass
82
+ * of its own overrides this (and `closeStore` if its client needs closing):
84
83
  *
85
84
  * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }
86
85
  */
87
86
  createStore() {
88
- return require_cloudflare_d1_env.d1Store(this.env);
87
+ throw new Error("JourneyRunner: override createStore, or build the runner with journeyWorker");
89
88
  }
90
89
  /** Called once `run` is over, success or not — release whatever `createStore` opened. */
91
90
  async closeStore(_store) {}
@@ -184,7 +183,6 @@ var JourneyRunner = class extends cloudflare_workers.WorkflowEntrypoint {
184
183
  }
185
184
  }
186
185
  };
187
- //#endregion
188
186
  exports.JourneyRunner = JourneyRunner;
189
187
 
190
188
  //# sourceMappingURL=runner.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.cjs","names":["isRetryable","NonRetryableError","WAKE_EVENT_TYPE","wakeExpired","WorkflowEntrypoint","d1Store","cloudflareJourneyBinding","resolveRuntime","WebhookMessageSender","LogMessageSender","RegistryActionInvoker","executeJourney"],"sources":["../../src/cloudflare/runner.ts"],"sourcesContent":["import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from 'cloudflare:workers';\nimport { NonRetryableError } from 'cloudflare:workflows';\nimport type { Contract } from '../contract';\nimport { type RegisteredAction, RegistryActionInvoker } from '../engine/actions';\nimport type {\n ActionInvoker,\n EngineStep,\n JourneyObserver,\n JourneyOutcome,\n MessageSender,\n MessageValidator,\n} from '../engine/ports';\nimport { isRetryable } from '../engine/retry';\nimport { type JourneyRunParts, executeJourney } from '../host/execute';\nimport { type JourneyEnv, type JourneyParams, WAKE_EVENT_TYPE } from '../host/platform';\nimport { LogMessageSender, WebhookMessageSender } from '../host/senders';\nimport { type JourneyRuntimeOptions, resolveRuntime } from '../runtime';\nimport type { JourneyStore } from '../store/index';\nimport { cloudflareJourneyBinding, wakeExpired } from './bindings';\nimport { d1Store } from './d1-env';\n\n/**\n * Adapts CF's WorkflowStep to EngineStep.\n * subscribe/unsubscribe write the subscription table inside durable steps (the\n * router wakes instances from that table); waitForWake parks on CF's\n * waitForEvent, which signals a timeout by throwing — and so does every other\n * failure in there, so only the clock, against the checkpointed deadline, can\n * tell them apart (see wakeExpired).\n */\nclass CfEngineStep implements EngineStep {\n constructor(\n private readonly step: WorkflowStep,\n private readonly store: JourneyStore,\n private readonly userId: string,\n private readonly instanceId: string\n ) {}\n\n /**\n * A failure a retry would only repeat (`isRetryable`: a template refusing its props, the\n * contract refusing an emitted event, a provider rejecting the request) ends the step at\n * once instead of burning the retry budget. The engine recognizes a NonRetryableError by its\n * `name`, so the original's name is not written over it — the original travels as `cause`.\n */\n do<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return this.step.do(name, async () => {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && !isRetryable(error)) {\n const permanent = new NonRetryableError(error.message);\n permanent.cause = error;\n throw permanent;\n }\n throw error;\n }\n });\n }\n\n sleep(name: string, ms: number): Promise<void> {\n return this.step.sleep(name, ms);\n }\n\n subscribe(name: string, events: readonly string[]): Promise<void> {\n // Idempotent in the store: the interpreter re-subscribes on every wait\n // attempt (one-shot-callback contract) and registrations persist here.\n return this.step.do(name, () =>\n this.store.subscribe(this.instanceId, this.userId, events, Date.now())\n );\n }\n\n unsubscribe(name: string): Promise<void> {\n return this.step.do(name, () => this.store.unsubscribe(this.instanceId));\n }\n\n async waitForWake(\n name: string,\n { timeoutMs, deadlineMs }: { timeoutMs: number; deadlineMs: number }\n ): Promise<'event' | 'timeout'> {\n try {\n await this.step.waitForEvent(name, { type: WAKE_EVENT_TYPE, timeout: timeoutMs });\n return 'event';\n } catch (error) {\n /*\n * Only the deadline can tell a real timeout from a failure (see wakeExpired). The\n * deadline is the interpreter's checkpoint, so the verdict is the same on the attempt\n * that parked and on a replay after an eviction — which is where the wait usually\n * resurfaces: the instance is rebuilt, the wait is already over, and the first thing to\n * run is this step. The verdict is checkpointed too, so later replays reuse it.\n */\n const timedOut = await this.step.do(`${name}:timed-out`, async () =>\n wakeExpired(deadlineMs, Date.now())\n );\n if (timedOut) return 'timeout';\n throw error;\n }\n }\n}\n\n/**\n * The generic journey executor: one class runs every workflow, because IR is\n * data. It is loaded from the store by the contentHash pinned at entry —\n * content addressing makes it immutable, so reading it outside a step is\n * replay-safe.\n */\nexport class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {\n /**\n * The data plane. D1 from the env by default; an app on Postgres\n * overrides this (and `closeStore` if its client needs closing):\n *\n * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }\n */\n protected createStore(): JourneyStore {\n return d1Store(this.env);\n }\n\n /** Called once `run` is over, success or not — release whatever `createStore` opened. */\n protected async closeStore(_store: JourneyStore): Promise<void> {}\n\n private adapted: JourneyEnv | undefined;\n\n /**\n * The env a run ingests its emitted events with: the Workflow binding behind the host's port,\n * so an instance the platform no longer knows answers `InstanceNotFoundError` (what lets the\n * host drop its wakes). Built once per instance.\n */\n protected hostEnv(): JourneyEnv {\n return (this.adapted ??= { ...this.env, JOURNEY: cloudflareJourneyBinding(this.env.JOURNEY) });\n }\n\n /**\n * Runtime options for this instance — typed configuration, resolved by the app (typically\n * `resolveRuntime(config.runtime, mode)` over its workflow.config.ts, with the mode coming from\n * an ENVIRONMENT var). The instance params are passed so the decision can also be per user:\n * a tester account in production can run in fast-forward while everyone else runs in real\n * time. Defaults: real time, quiet.\n *\n * protected override runtime({ userId }) {\n * return resolveRuntime(workflowConfig.runtime, isTester(userId) ? 'test' : this.env.ENVIRONMENT);\n * }\n */\n protected runtime(_params: JourneyParams): JourneyRuntimeOptions {\n return resolveRuntime(undefined, 'production');\n }\n\n /**\n * Message outlet; an app overrides this to plug in real channels (say\n * an EmailSender over a transport with a react-email renderer). By default it picks the webhook\n * or logging sender based on the environment.\n */\n protected createMessageSender(): MessageSender {\n return this.env.MESSAGE_WEBHOOK_URL\n ? new WebhookMessageSender(this.env.MESSAGE_WEBHOOK_URL)\n : new LogMessageSender();\n }\n\n /**\n * Custom-action registry; an app overrides this returning the same\n * `action(...)` objects its workflows reference (an ActionRef is a\n * RegisteredAction structurally) — the code plane of the dual-plane model:\n *\n * protected override actions() { return [syncCrm, issueCoupon]; }\n */\n protected actions(): readonly RegisteredAction[] {\n return [];\n }\n\n /**\n * The contract events this journey emits (`.sendEvent()`) are checked\n * against, exactly like ingest; journeyWorker passes its config's.\n */\n protected contract(): Contract | undefined {\n return undefined;\n }\n\n /**\n * Template props check before every send; an app overrides this with\n * `registryValidator({ emails, pushes })` (journeyWorker does it from its\n * registries). By default props go out as resolved.\n */\n protected createMessageValidator(): MessageValidator | undefined {\n return undefined;\n }\n\n /**\n * Reporting hooks: node arrivals, every copy sent, how each instance ended. The host stores\n * what it needs for its dashboards; by default nothing is reported.\n */\n protected createObserver(_store: JourneyStore): JourneyObserver | undefined {\n return undefined;\n }\n\n /** Override for a different version policy ('warn' by default) or a fully custom invoker (e.g. webhook degradation for hosted tenants). */\n protected createActionInvoker(): ActionInvoker {\n return new RegistryActionInvoker(this.actions());\n }\n\n /**\n * Everything one run is wired to. By default it is composed from the methods above; a host\n * that assembles the whole set itself (journeyWorker) overrides this one instead.\n */\n protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts {\n return {\n store,\n env: this.hostEnv(),\n runtime: this.runtime(params),\n messages: this.createMessageSender(),\n actions: this.createActionInvoker(),\n contract: this.contract(),\n validator: this.createMessageValidator(),\n observer: this.createObserver(store),\n };\n }\n\n async run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome> {\n const store = this.createStore();\n try {\n const { userId } = event.payload;\n return await executeJourney(\n {\n instanceId: event.instanceId,\n params: event.payload,\n // Trigger-event creation time: replay-stable, unlike Date.now() here\n enteredAtMs: event.timestamp.getTime(),\n step: new CfEngineStep(step, store, userId, event.instanceId),\n },\n this.createRunParts(store, event.payload)\n );\n } finally {\n await this.closeStore(store);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6BA,IAAM,eAAN,MAAyC;CAEpB;CACA;CACA;CACA;CAJnB,YACE,MACA,OACA,QACA,YACA;EAJiB,KAAA,OAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,aAAA;CAChB;;;;;;;CAQH,GAAM,MAAc,IAAkC;EACpD,OAAO,KAAK,KAAK,GAAG,MAAM,YAAY;GACpC,IAAI;IACF,OAAO,MAAM,GAAG;GAClB,SAAS,OAAO;IACd,IAAI,iBAAiB,SAAS,CAACA,qBAAAA,YAAY,KAAK,GAAG;KACjD,MAAM,YAAY,IAAIC,qBAAAA,kBAAkB,MAAM,OAAO;KACrD,UAAU,QAAQ;KAClB,MAAM;IACR;IACA,MAAM;GACR;EACF,CAAC;CACH;CAEA,MAAM,MAAc,IAA2B;EAC7C,OAAO,KAAK,KAAK,MAAM,MAAM,EAAE;CACjC;CAEA,UAAU,MAAc,QAA0C;EAGhE,OAAO,KAAK,KAAK,GAAG,YAClB,KAAK,MAAM,UAAU,KAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK,IAAI,CAAC,CACvE;CACF;CAEA,YAAY,MAA6B;EACvC,OAAO,KAAK,KAAK,GAAG,YAAY,KAAK,MAAM,YAAY,KAAK,UAAU,CAAC;CACzE;CAEA,MAAM,YACJ,MACA,EAAE,WAAW,cACiB;EAC9B,IAAI;GACF,MAAM,KAAK,KAAK,aAAa,MAAM;IAAE,MAAMC,sBAAAA;IAAiB,SAAS;GAAU,CAAC;GAChF,OAAO;EACT,SAAS,OAAO;GAWd,IAAI,MAHmB,KAAK,KAAK,GAAG,GAAG,KAAK,aAAa,YACvDC,4BAAAA,YAAY,YAAY,KAAK,IAAI,CAAC,CACpC,GACc,OAAO;GACrB,MAAM;EACR;CACF;AACF;;;;;;;AAQA,IAAa,gBAAb,cAAmCC,mBAAAA,mBAA8C;;;;;;;CAO/E,cAAsC;EACpC,OAAOC,0BAAAA,QAAQ,KAAK,GAAG;CACzB;;CAGA,MAAgB,WAAW,QAAqC,CAAC;CAEjE;;;;;;CAOA,UAAgC;EAC9B,OAAQ,KAAK,YAAY;GAAE,GAAG,KAAK;GAAK,SAASC,4BAAAA,yBAAyB,KAAK,IAAI,OAAO;EAAE;CAC9F;;;;;;;;;;;;CAaA,QAAkB,SAA+C;EAC/D,OAAOC,gBAAAA,eAAe,KAAA,GAAW,YAAY;CAC/C;;;;;;CAOA,sBAA+C;EAC7C,OAAO,KAAK,IAAI,sBACZ,IAAIC,qBAAAA,qBAAqB,KAAK,IAAI,mBAAmB,IACrD,IAAIC,qBAAAA,iBAAiB;CAC3B;;;;;;;;CASA,UAAiD;EAC/C,OAAO,CAAC;CACV;;;;;CAMA,WAA2C,CAE3C;;;;;;CAOA,yBAAiE,CAEjE;;;;;CAMA,eAAyB,QAAmD,CAE5E;;CAGA,sBAA+C;EAC7C,OAAO,IAAIC,uBAAAA,sBAAsB,KAAK,QAAQ,CAAC;CACjD;;;;;CAMA,eAAyB,OAAqB,QAAwC;EACpF,OAAO;GACL;GACA,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ,MAAM;GAC5B,UAAU,KAAK,oBAAoB;GACnC,SAAS,KAAK,oBAAoB;GAClC,UAAU,KAAK,SAAS;GACxB,WAAW,KAAK,uBAAuB;GACvC,UAAU,KAAK,eAAe,KAAK;EACrC;CACF;CAEA,MAAM,IAAI,OAAqC,MAA6C;EAC1F,MAAM,QAAQ,KAAK,YAAY;EAC/B,IAAI;GACF,MAAM,EAAE,WAAW,MAAM;GACzB,OAAO,MAAMC,qBAAAA,eACX;IACE,YAAY,MAAM;IAClB,QAAQ,MAAM;IAEd,aAAa,MAAM,UAAU,QAAQ;IACrC,MAAM,IAAI,aAAa,MAAM,OAAO,QAAQ,MAAM,UAAU;GAC9D,GACA,KAAK,eAAe,OAAO,MAAM,OAAO,CAC1C;EACF,UAAU;GACR,MAAM,KAAK,WAAW,KAAK;EAC7B;CACF;AACF"}
1
+ {"version":3,"file":"runner.cjs","names":["isRetryable","NonRetryableError","WAKE_EVENT_TYPE","wakeExpired","WorkflowEntrypoint","cloudflareJourneyBinding","resolveRuntime","WebhookMessageSender","LogMessageSender","RegistryActionInvoker","executeJourney"],"sources":["../../src/cloudflare/runner.ts"],"sourcesContent":["import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from 'cloudflare:workers';\nimport { NonRetryableError } from 'cloudflare:workflows';\nimport type { Contract } from '../contract';\nimport { type RegisteredAction, RegistryActionInvoker } from '../engine/actions';\nimport type {\n ActionInvoker,\n EngineStep,\n JourneyObserver,\n JourneyOutcome,\n MessageSender,\n MessageValidator,\n} from '../engine/ports';\nimport { isRetryable } from '../engine/retry';\nimport { type JourneyRunParts, executeJourney } from '../host/execute';\nimport { type JourneyEnv, type JourneyParams, WAKE_EVENT_TYPE } from '../host/platform';\nimport { LogMessageSender, WebhookMessageSender } from '../host/senders';\nimport { type JourneyRuntimeOptions, resolveRuntime } from '../runtime';\nimport type { JourneyStore } from '../store/index';\nimport { cloudflareJourneyBinding, wakeExpired } from './bindings';\n\n/**\n * Adapts CF's WorkflowStep to EngineStep.\n * subscribe/unsubscribe write the subscription table inside durable steps (the\n * router wakes instances from that table); waitForWake parks on CF's\n * waitForEvent, which signals a timeout by throwing — and so does every other\n * failure in there, so only the clock, against the checkpointed deadline, can\n * tell them apart (see wakeExpired).\n */\nclass CfEngineStep implements EngineStep {\n constructor(\n private readonly step: WorkflowStep,\n private readonly store: JourneyStore,\n private readonly userId: string,\n private readonly instanceId: string\n ) {}\n\n /**\n * A failure a retry would only repeat (`isRetryable`: a template refusing its props, the\n * contract refusing an emitted event, a provider rejecting the request) ends the step at\n * once instead of burning the retry budget. The engine recognizes a NonRetryableError by its\n * `name`, so the original's name is not written over it — the original travels as `cause`.\n */\n do<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return this.step.do(name, async () => {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && !isRetryable(error)) {\n const permanent = new NonRetryableError(error.message);\n permanent.cause = error;\n throw permanent;\n }\n throw error;\n }\n });\n }\n\n sleep(name: string, ms: number): Promise<void> {\n return this.step.sleep(name, ms);\n }\n\n subscribe(name: string, events: readonly string[]): Promise<void> {\n // Idempotent in the store: the interpreter re-subscribes on every wait\n // attempt (one-shot-callback contract) and registrations persist here.\n return this.step.do(name, () =>\n this.store.subscribe(this.instanceId, this.userId, events, Date.now())\n );\n }\n\n unsubscribe(name: string): Promise<void> {\n return this.step.do(name, () => this.store.unsubscribe(this.instanceId));\n }\n\n async waitForWake(\n name: string,\n { timeoutMs, deadlineMs }: { timeoutMs: number; deadlineMs: number }\n ): Promise<'event' | 'timeout'> {\n try {\n await this.step.waitForEvent(name, { type: WAKE_EVENT_TYPE, timeout: timeoutMs });\n return 'event';\n } catch (error) {\n /*\n * Only the deadline can tell a real timeout from a failure (see wakeExpired). The\n * deadline is the interpreter's checkpoint, so the verdict is the same on the attempt\n * that parked and on a replay after an eviction — which is where the wait usually\n * resurfaces: the instance is rebuilt, the wait is already over, and the first thing to\n * run is this step. The verdict is checkpointed too, so later replays reuse it.\n */\n const timedOut = await this.step.do(`${name}:timed-out`, async () =>\n wakeExpired(deadlineMs, Date.now())\n );\n if (timedOut) return 'timeout';\n throw error;\n }\n }\n}\n\n/**\n * The generic journey executor: one class runs every workflow, because IR is\n * data. It is loaded from the store by the contentHash pinned at entry —\n * content addressing makes it immutable, so reading it outside a step is\n * replay-safe.\n */\nexport class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {\n /**\n * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass\n * of its own overrides this (and `closeStore` if its client needs closing):\n *\n * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }\n */\n protected createStore(): JourneyStore {\n throw new Error('JourneyRunner: override createStore, or build the runner with journeyWorker');\n }\n\n /** Called once `run` is over, success or not — release whatever `createStore` opened. */\n protected async closeStore(_store: JourneyStore): Promise<void> {}\n\n private adapted: JourneyEnv | undefined;\n\n /**\n * The env a run ingests its emitted events with: the Workflow binding behind the host's port,\n * so an instance the platform no longer knows answers `InstanceNotFoundError` (what lets the\n * host drop its wakes). Built once per instance.\n */\n protected hostEnv(): JourneyEnv {\n return (this.adapted ??= { ...this.env, JOURNEY: cloudflareJourneyBinding(this.env.JOURNEY) });\n }\n\n /**\n * Runtime options for this instance — typed configuration, resolved by the app (typically\n * `resolveRuntime(config.runtime, mode)` over its workflow.config.ts, with the mode coming from\n * an ENVIRONMENT var). The instance params are passed so the decision can also be per user:\n * a tester account in production can run in fast-forward while everyone else runs in real\n * time. Defaults: real time, quiet.\n *\n * protected override runtime({ userId }) {\n * return resolveRuntime(workflowConfig.runtime, isTester(userId) ? 'test' : this.env.ENVIRONMENT);\n * }\n */\n protected runtime(_params: JourneyParams): JourneyRuntimeOptions {\n return resolveRuntime(undefined, 'production');\n }\n\n /**\n * Message outlet; an app overrides this to plug in real channels (say\n * an EmailSender over a transport with a react-email renderer). By default it picks the webhook\n * or logging sender based on the environment.\n */\n protected createMessageSender(): MessageSender {\n return this.env.MESSAGE_WEBHOOK_URL\n ? new WebhookMessageSender(this.env.MESSAGE_WEBHOOK_URL)\n : new LogMessageSender();\n }\n\n /**\n * Custom-action registry; an app overrides this returning the same\n * `action(...)` objects its workflows reference (an ActionRef is a\n * RegisteredAction structurally) — the code plane of the dual-plane model:\n *\n * protected override actions() { return [syncCrm, issueCoupon]; }\n */\n protected actions(): readonly RegisteredAction[] {\n return [];\n }\n\n /**\n * The contract events this journey emits (`.sendEvent()`) are checked\n * against, exactly like ingest; journeyWorker passes its config's.\n */\n protected contract(): Contract | undefined {\n return undefined;\n }\n\n /**\n * Template props check before every send; an app overrides this with\n * `registryValidator({ emails, pushes })` (journeyWorker does it from its\n * registries). By default props go out as resolved.\n */\n protected createMessageValidator(): MessageValidator | undefined {\n return undefined;\n }\n\n /**\n * Reporting hooks: node arrivals, every copy sent, how each instance ended. The host stores\n * what it needs for its dashboards; by default nothing is reported.\n */\n protected createObserver(_store: JourneyStore): JourneyObserver | undefined {\n return undefined;\n }\n\n /** Override for a different version policy ('warn' by default) or a fully custom invoker (e.g. webhook degradation for hosted tenants). */\n protected createActionInvoker(): ActionInvoker {\n return new RegistryActionInvoker(this.actions());\n }\n\n /**\n * Everything one run is wired to. By default it is composed from the methods above; a host\n * that assembles the whole set itself (journeyWorker) overrides this one instead.\n */\n protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts {\n return {\n store,\n env: this.hostEnv(),\n runtime: this.runtime(params),\n messages: this.createMessageSender(),\n actions: this.createActionInvoker(),\n contract: this.contract(),\n validator: this.createMessageValidator(),\n observer: this.createObserver(store),\n };\n }\n\n async run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome> {\n const store = this.createStore();\n try {\n const { userId } = event.payload;\n return await executeJourney(\n {\n instanceId: event.instanceId,\n params: event.payload,\n // Trigger-event creation time: replay-stable, unlike Date.now() here\n enteredAtMs: event.timestamp.getTime(),\n step: new CfEngineStep(step, store, userId, event.instanceId),\n },\n this.createRunParts(store, event.payload)\n );\n } finally {\n await this.closeStore(store);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA4BA,IAAM,eAAN,MAAyC;CAEpB;CACA;CACA;CACA;CAJnB,YACE,MACA,OACA,QACA,YACA;EAJiB,KAAA,OAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,aAAA;CAChB;;;;;;;CAQH,GAAM,MAAc,IAAkC;EACpD,OAAO,KAAK,KAAK,GAAG,MAAM,YAAY;GACpC,IAAI;IACF,OAAO,MAAM,GAAG;GAClB,SAAS,OAAO;IACd,IAAI,iBAAiB,SAAS,CAACA,qBAAAA,YAAY,KAAK,GAAG;KACjD,MAAM,YAAY,IAAIC,qBAAAA,kBAAkB,MAAM,OAAO;KACrD,UAAU,QAAQ;KAClB,MAAM;IACR;IACA,MAAM;GACR;EACF,CAAC;CACH;CAEA,MAAM,MAAc,IAA2B;EAC7C,OAAO,KAAK,KAAK,MAAM,MAAM,EAAE;CACjC;CAEA,UAAU,MAAc,QAA0C;EAGhE,OAAO,KAAK,KAAK,GAAG,YAClB,KAAK,MAAM,UAAU,KAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK,IAAI,CAAC,CACvE;CACF;CAEA,YAAY,MAA6B;EACvC,OAAO,KAAK,KAAK,GAAG,YAAY,KAAK,MAAM,YAAY,KAAK,UAAU,CAAC;CACzE;CAEA,MAAM,YACJ,MACA,EAAE,WAAW,cACiB;EAC9B,IAAI;GACF,MAAM,KAAK,KAAK,aAAa,MAAM;IAAE,MAAMC,sBAAAA;IAAiB,SAAS;GAAU,CAAC;GAChF,OAAO;EACT,SAAS,OAAO;GAWd,IAAI,MAHmB,KAAK,KAAK,GAAG,GAAG,KAAK,aAAa,YACvDC,4BAAAA,YAAY,YAAY,KAAK,IAAI,CAAC,CACpC,GACc,OAAO;GACrB,MAAM;EACR;CACF;AACF;;;;;;;AAQA,IAAa,gBAAb,cAAmCC,mBAAAA,mBAA8C;;;;;;;CAO/E,cAAsC;EACpC,MAAM,IAAI,MAAM,6EAA6E;CAC/F;;CAGA,MAAgB,WAAW,QAAqC,CAAC;CAEjE;;;;;;CAOA,UAAgC;EAC9B,OAAQ,KAAK,YAAY;GAAE,GAAG,KAAK;GAAK,SAASC,4BAAAA,yBAAyB,KAAK,IAAI,OAAO;EAAE;CAC9F;;;;;;;;;;;;CAaA,QAAkB,SAA+C;EAC/D,OAAOC,gBAAAA,eAAe,KAAA,GAAW,YAAY;CAC/C;;;;;;CAOA,sBAA+C;EAC7C,OAAO,KAAK,IAAI,sBACZ,IAAIC,qBAAAA,qBAAqB,KAAK,IAAI,mBAAmB,IACrD,IAAIC,qBAAAA,iBAAiB;CAC3B;;;;;;;;CASA,UAAiD;EAC/C,OAAO,CAAC;CACV;;;;;CAMA,WAA2C,CAE3C;;;;;;CAOA,yBAAiE,CAEjE;;;;;CAMA,eAAyB,QAAmD,CAE5E;;CAGA,sBAA+C;EAC7C,OAAO,IAAIC,uBAAAA,sBAAsB,KAAK,QAAQ,CAAC;CACjD;;;;;CAMA,eAAyB,OAAqB,QAAwC;EACpF,OAAO;GACL;GACA,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ,MAAM;GAC5B,UAAU,KAAK,oBAAoB;GACnC,SAAS,KAAK,oBAAoB;GAClC,UAAU,KAAK,SAAS;GACxB,WAAW,KAAK,uBAAuB;GACvC,UAAU,KAAK,eAAe,KAAK;EACrC;CACF;CAEA,MAAM,IAAI,OAAqC,MAA6C;EAC1F,MAAM,QAAQ,KAAK,YAAY;EAC/B,IAAI;GACF,MAAM,EAAE,WAAW,MAAM;GACzB,OAAO,MAAMC,qBAAAA,eACX;IACE,YAAY,MAAM;IAClB,QAAQ,MAAM;IAEd,aAAa,MAAM,UAAU,QAAQ;IACrC,MAAM,IAAI,aAAa,MAAM,OAAO,QAAQ,MAAM,UAAU;GAC9D,GACA,KAAK,eAAe,OAAO,MAAM,OAAO,CAC1C;EACF,UAAU;GACR,MAAM,KAAK,WAAW,KAAK;EAC7B;CACF;AACF"}
@@ -1,12 +1,11 @@
1
1
  import { ActionInvoker, JourneyObserver, JourneyOutcome, MessageSender, MessageValidator } from "../engine/ports.cjs";
2
2
  import { RegisteredAction } from "../engine/actions.cjs";
3
- import { JourneyEnv, JourneyParams } from "../host/platform.cjs";
4
3
  import { JourneyStore } from "../store/index.cjs";
5
4
  import { Contract } from "../contract.cjs";
6
5
  import { JourneyRuntimeOptions } from "../runtime.cjs";
6
+ import { JourneyEnv, JourneyParams } from "../host/platform.cjs";
7
7
  import { JourneyRunParts } from "../host/execute.cjs";
8
8
  import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers";
9
- //#region src/cloudflare/runner.d.ts
10
9
  /**
11
10
  * The generic journey executor: one class runs every workflow, because IR is
12
11
  * data. It is loaded from the store by the contentHash pinned at entry —
@@ -15,8 +14,8 @@ import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:work
15
14
  */
16
15
  export declare class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {
17
16
  /**
18
- * The data plane. D1 from the env by default; an app on Postgres
19
- * overrides this (and `closeStore` if its client needs closing):
17
+ * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass
18
+ * of its own overrides this (and `closeStore` if its client needs closing):
20
19
  *
21
20
  * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }
22
21
  */
@@ -81,5 +80,4 @@ export declare class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, Journe
81
80
  protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts;
82
81
  run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome>;
83
82
  }
84
- //#endregion
85
83
  //# sourceMappingURL=runner.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.cts","names":[],"sources":["../../src/cloudflare/runner.ts"],"mappings":";;;;;;;;;;;;;;;qBAwGa,sBAAsB,mBAAmB,YAAY;;;;;;;YAOtD,eAAe;;YAKT,WAAW,QAAQ,eAAe;UAE1C;;;;;;YAOE,WAAW;;;;;;;;;;;;YAeX,QAAQ,SAAS,gBAAgB;;;;;;YASjC,uBAAuB;;;;;;;;YAavB,oBAAoB;;;;;YAQpB,YAAY;;;;;;YASZ,0BAA0B;;;;;YAQ1B,eAAe,QAAQ,eAAe;;YAKtC,uBAAuB;;;;;YAQvB,eAAe,OAAO,cAAc,QAAQ,gBAAgB;EAahE,IAAI,OAAO,cAAc,gBAAgB,MAAM,eAAe,QAAQ"}
1
+ {"version":3,"file":"runner.d.cts","names":[],"sources":["../../src/cloudflare/runner.ts"],"mappings":";;;;;;;;;;;;;;qBAuGa,sBAAsB,mBAAmB,YAAY;;;;;;;YAOtD,eAAe;;YAKT,WAAW,QAAQ,eAAe;UAE1C;;;;;;YAOE,WAAW;;;;;;;;;;;;YAeX,QAAQ,SAAS,gBAAgB;;;;;;YASjC,uBAAuB;;;;;;;;YAavB,oBAAoB;;;;;YAQpB,YAAY;;;;;;YASZ,0BAA0B;;;;;YAQ1B,eAAe,QAAQ,eAAe;;YAKtC,uBAAuB;;;;;YAQvB,eAAe,OAAO,cAAc,QAAQ,gBAAgB;EAahE,IAAI,OAAO,cAAc,gBAAgB,MAAM,eAAe,QAAQ"}
@@ -1,12 +1,11 @@
1
1
  import { ActionInvoker, JourneyObserver, JourneyOutcome, MessageSender, MessageValidator } from "../engine/ports.mjs";
2
2
  import { RegisteredAction } from "../engine/actions.mjs";
3
- import { JourneyEnv, JourneyParams } from "../host/platform.mjs";
4
3
  import { JourneyStore } from "../store/index.mjs";
5
4
  import { Contract } from "../contract.mjs";
6
5
  import { JourneyRuntimeOptions } from "../runtime.mjs";
6
+ import { JourneyEnv, JourneyParams } from "../host/platform.mjs";
7
7
  import { JourneyRunParts } from "../host/execute.mjs";
8
8
  import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers";
9
- //#region src/cloudflare/runner.d.ts
10
9
  /**
11
10
  * The generic journey executor: one class runs every workflow, because IR is
12
11
  * data. It is loaded from the store by the contentHash pinned at entry —
@@ -15,8 +14,8 @@ import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:work
15
14
  */
16
15
  export declare class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {
17
16
  /**
18
- * The data plane. D1 from the env by default; an app on Postgres
19
- * overrides this (and `closeStore` if its client needs closing):
17
+ * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass
18
+ * of its own overrides this (and `closeStore` if its client needs closing):
20
19
  *
21
20
  * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }
22
21
  */
@@ -81,5 +80,4 @@ export declare class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, Journe
81
80
  protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts;
82
81
  run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome>;
83
82
  }
84
- //#endregion
85
83
  //# sourceMappingURL=runner.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.mts","names":[],"sources":["../../src/cloudflare/runner.ts"],"mappings":";;;;;;;;;;;;;;;qBAwGa,sBAAsB,mBAAmB,YAAY;;;;;;;YAOtD,eAAe;;YAKT,WAAW,QAAQ,eAAe;UAE1C;;;;;;YAOE,WAAW;;;;;;;;;;;;YAeX,QAAQ,SAAS,gBAAgB;;;;;;YASjC,uBAAuB;;;;;;;;YAavB,oBAAoB;;;;;YAQpB,YAAY;;;;;;YASZ,0BAA0B;;;;;YAQ1B,eAAe,QAAQ,eAAe;;YAKtC,uBAAuB;;;;;YAQvB,eAAe,OAAO,cAAc,QAAQ,gBAAgB;EAahE,IAAI,OAAO,cAAc,gBAAgB,MAAM,eAAe,QAAQ"}
1
+ {"version":3,"file":"runner.d.mts","names":[],"sources":["../../src/cloudflare/runner.ts"],"mappings":";;;;;;;;;;;;;;qBAuGa,sBAAsB,mBAAmB,YAAY;;;;;;;YAOtD,eAAe;;YAKT,WAAW,QAAQ,eAAe;UAE1C;;;;;;YAOE,WAAW;;;;;;;;;;;;YAeX,QAAQ,SAAS,gBAAgB;;;;;;YASjC,uBAAuB;;;;;;;;YAavB,oBAAoB;;;;;YAQpB,YAAY;;;;;;YASZ,0BAA0B;;;;;YAQ1B,eAAe,QAAQ,eAAe;;YAKtC,uBAAuB;;;;;YAQvB,eAAe,OAAO,cAAc,QAAQ,gBAAgB;EAahE,IAAI,OAAO,cAAc,gBAAgB,MAAM,eAAe,QAAQ"}
@@ -1,6 +1,5 @@
1
1
  import { isRetryable } from "../engine/retry.mjs";
2
2
  import { resolveRuntime } from "../runtime.mjs";
3
- import { d1Store } from "./d1-env.mjs";
4
3
  import { WAKE_EVENT_TYPE } from "../host/platform.mjs";
5
4
  import { executeJourney } from "../host/execute.mjs";
6
5
  import { RegistryActionInvoker } from "../engine/actions.mjs";
@@ -8,7 +7,7 @@ import { LogMessageSender, WebhookMessageSender } from "../host/senders.mjs";
8
7
  import { cloudflareJourneyBinding, wakeExpired } from "./bindings.mjs";
9
8
  import { WorkflowEntrypoint } from "cloudflare:workers";
10
9
  import { NonRetryableError } from "cloudflare:workflows";
11
- //#region src/cloudflare/runner.ts
10
+ // src/cloudflare/runner.ts
12
11
  /**
13
12
  * Adapts CF's WorkflowStep to EngineStep.
14
13
  * subscribe/unsubscribe write the subscription table inside durable steps (the
@@ -78,13 +77,13 @@ var CfEngineStep = class {
78
77
  */
79
78
  var JourneyRunner = class extends WorkflowEntrypoint {
80
79
  /**
81
- * The data plane. D1 from the env by default; an app on Postgres
82
- * overrides this (and `closeStore` if its client needs closing):
80
+ * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass
81
+ * of its own overrides this (and `closeStore` if its client needs closing):
83
82
  *
84
83
  * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }
85
84
  */
86
85
  createStore() {
87
- return d1Store(this.env);
86
+ throw new Error("JourneyRunner: override createStore, or build the runner with journeyWorker");
88
87
  }
89
88
  /** Called once `run` is over, success or not — release whatever `createStore` opened. */
90
89
  async closeStore(_store) {}
@@ -183,7 +182,6 @@ var JourneyRunner = class extends WorkflowEntrypoint {
183
182
  }
184
183
  }
185
184
  };
186
- //#endregion
187
185
  export { JourneyRunner };
188
186
 
189
187
  //# sourceMappingURL=runner.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.mjs","names":[],"sources":["../../src/cloudflare/runner.ts"],"sourcesContent":["import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from 'cloudflare:workers';\nimport { NonRetryableError } from 'cloudflare:workflows';\nimport type { Contract } from '../contract';\nimport { type RegisteredAction, RegistryActionInvoker } from '../engine/actions';\nimport type {\n ActionInvoker,\n EngineStep,\n JourneyObserver,\n JourneyOutcome,\n MessageSender,\n MessageValidator,\n} from '../engine/ports';\nimport { isRetryable } from '../engine/retry';\nimport { type JourneyRunParts, executeJourney } from '../host/execute';\nimport { type JourneyEnv, type JourneyParams, WAKE_EVENT_TYPE } from '../host/platform';\nimport { LogMessageSender, WebhookMessageSender } from '../host/senders';\nimport { type JourneyRuntimeOptions, resolveRuntime } from '../runtime';\nimport type { JourneyStore } from '../store/index';\nimport { cloudflareJourneyBinding, wakeExpired } from './bindings';\nimport { d1Store } from './d1-env';\n\n/**\n * Adapts CF's WorkflowStep to EngineStep.\n * subscribe/unsubscribe write the subscription table inside durable steps (the\n * router wakes instances from that table); waitForWake parks on CF's\n * waitForEvent, which signals a timeout by throwing — and so does every other\n * failure in there, so only the clock, against the checkpointed deadline, can\n * tell them apart (see wakeExpired).\n */\nclass CfEngineStep implements EngineStep {\n constructor(\n private readonly step: WorkflowStep,\n private readonly store: JourneyStore,\n private readonly userId: string,\n private readonly instanceId: string\n ) {}\n\n /**\n * A failure a retry would only repeat (`isRetryable`: a template refusing its props, the\n * contract refusing an emitted event, a provider rejecting the request) ends the step at\n * once instead of burning the retry budget. The engine recognizes a NonRetryableError by its\n * `name`, so the original's name is not written over it — the original travels as `cause`.\n */\n do<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return this.step.do(name, async () => {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && !isRetryable(error)) {\n const permanent = new NonRetryableError(error.message);\n permanent.cause = error;\n throw permanent;\n }\n throw error;\n }\n });\n }\n\n sleep(name: string, ms: number): Promise<void> {\n return this.step.sleep(name, ms);\n }\n\n subscribe(name: string, events: readonly string[]): Promise<void> {\n // Idempotent in the store: the interpreter re-subscribes on every wait\n // attempt (one-shot-callback contract) and registrations persist here.\n return this.step.do(name, () =>\n this.store.subscribe(this.instanceId, this.userId, events, Date.now())\n );\n }\n\n unsubscribe(name: string): Promise<void> {\n return this.step.do(name, () => this.store.unsubscribe(this.instanceId));\n }\n\n async waitForWake(\n name: string,\n { timeoutMs, deadlineMs }: { timeoutMs: number; deadlineMs: number }\n ): Promise<'event' | 'timeout'> {\n try {\n await this.step.waitForEvent(name, { type: WAKE_EVENT_TYPE, timeout: timeoutMs });\n return 'event';\n } catch (error) {\n /*\n * Only the deadline can tell a real timeout from a failure (see wakeExpired). The\n * deadline is the interpreter's checkpoint, so the verdict is the same on the attempt\n * that parked and on a replay after an eviction — which is where the wait usually\n * resurfaces: the instance is rebuilt, the wait is already over, and the first thing to\n * run is this step. The verdict is checkpointed too, so later replays reuse it.\n */\n const timedOut = await this.step.do(`${name}:timed-out`, async () =>\n wakeExpired(deadlineMs, Date.now())\n );\n if (timedOut) return 'timeout';\n throw error;\n }\n }\n}\n\n/**\n * The generic journey executor: one class runs every workflow, because IR is\n * data. It is loaded from the store by the contentHash pinned at entry —\n * content addressing makes it immutable, so reading it outside a step is\n * replay-safe.\n */\nexport class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {\n /**\n * The data plane. D1 from the env by default; an app on Postgres\n * overrides this (and `closeStore` if its client needs closing):\n *\n * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }\n */\n protected createStore(): JourneyStore {\n return d1Store(this.env);\n }\n\n /** Called once `run` is over, success or not — release whatever `createStore` opened. */\n protected async closeStore(_store: JourneyStore): Promise<void> {}\n\n private adapted: JourneyEnv | undefined;\n\n /**\n * The env a run ingests its emitted events with: the Workflow binding behind the host's port,\n * so an instance the platform no longer knows answers `InstanceNotFoundError` (what lets the\n * host drop its wakes). Built once per instance.\n */\n protected hostEnv(): JourneyEnv {\n return (this.adapted ??= { ...this.env, JOURNEY: cloudflareJourneyBinding(this.env.JOURNEY) });\n }\n\n /**\n * Runtime options for this instance — typed configuration, resolved by the app (typically\n * `resolveRuntime(config.runtime, mode)` over its workflow.config.ts, with the mode coming from\n * an ENVIRONMENT var). The instance params are passed so the decision can also be per user:\n * a tester account in production can run in fast-forward while everyone else runs in real\n * time. Defaults: real time, quiet.\n *\n * protected override runtime({ userId }) {\n * return resolveRuntime(workflowConfig.runtime, isTester(userId) ? 'test' : this.env.ENVIRONMENT);\n * }\n */\n protected runtime(_params: JourneyParams): JourneyRuntimeOptions {\n return resolveRuntime(undefined, 'production');\n }\n\n /**\n * Message outlet; an app overrides this to plug in real channels (say\n * an EmailSender over a transport with a react-email renderer). By default it picks the webhook\n * or logging sender based on the environment.\n */\n protected createMessageSender(): MessageSender {\n return this.env.MESSAGE_WEBHOOK_URL\n ? new WebhookMessageSender(this.env.MESSAGE_WEBHOOK_URL)\n : new LogMessageSender();\n }\n\n /**\n * Custom-action registry; an app overrides this returning the same\n * `action(...)` objects its workflows reference (an ActionRef is a\n * RegisteredAction structurally) — the code plane of the dual-plane model:\n *\n * protected override actions() { return [syncCrm, issueCoupon]; }\n */\n protected actions(): readonly RegisteredAction[] {\n return [];\n }\n\n /**\n * The contract events this journey emits (`.sendEvent()`) are checked\n * against, exactly like ingest; journeyWorker passes its config's.\n */\n protected contract(): Contract | undefined {\n return undefined;\n }\n\n /**\n * Template props check before every send; an app overrides this with\n * `registryValidator({ emails, pushes })` (journeyWorker does it from its\n * registries). By default props go out as resolved.\n */\n protected createMessageValidator(): MessageValidator | undefined {\n return undefined;\n }\n\n /**\n * Reporting hooks: node arrivals, every copy sent, how each instance ended. The host stores\n * what it needs for its dashboards; by default nothing is reported.\n */\n protected createObserver(_store: JourneyStore): JourneyObserver | undefined {\n return undefined;\n }\n\n /** Override for a different version policy ('warn' by default) or a fully custom invoker (e.g. webhook degradation for hosted tenants). */\n protected createActionInvoker(): ActionInvoker {\n return new RegistryActionInvoker(this.actions());\n }\n\n /**\n * Everything one run is wired to. By default it is composed from the methods above; a host\n * that assembles the whole set itself (journeyWorker) overrides this one instead.\n */\n protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts {\n return {\n store,\n env: this.hostEnv(),\n runtime: this.runtime(params),\n messages: this.createMessageSender(),\n actions: this.createActionInvoker(),\n contract: this.contract(),\n validator: this.createMessageValidator(),\n observer: this.createObserver(store),\n };\n }\n\n async run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome> {\n const store = this.createStore();\n try {\n const { userId } = event.payload;\n return await executeJourney(\n {\n instanceId: event.instanceId,\n params: event.payload,\n // Trigger-event creation time: replay-stable, unlike Date.now() here\n enteredAtMs: event.timestamp.getTime(),\n step: new CfEngineStep(step, store, userId, event.instanceId),\n },\n this.createRunParts(store, event.payload)\n );\n } finally {\n await this.closeStore(store);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6BA,IAAM,eAAN,MAAyC;CAEpB;CACA;CACA;CACA;CAJnB,YACE,MACA,OACA,QACA,YACA;EAJiB,KAAA,OAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,aAAA;CAChB;;;;;;;CAQH,GAAM,MAAc,IAAkC;EACpD,OAAO,KAAK,KAAK,GAAG,MAAM,YAAY;GACpC,IAAI;IACF,OAAO,MAAM,GAAG;GAClB,SAAS,OAAO;IACd,IAAI,iBAAiB,SAAS,CAAC,YAAY,KAAK,GAAG;KACjD,MAAM,YAAY,IAAI,kBAAkB,MAAM,OAAO;KACrD,UAAU,QAAQ;KAClB,MAAM;IACR;IACA,MAAM;GACR;EACF,CAAC;CACH;CAEA,MAAM,MAAc,IAA2B;EAC7C,OAAO,KAAK,KAAK,MAAM,MAAM,EAAE;CACjC;CAEA,UAAU,MAAc,QAA0C;EAGhE,OAAO,KAAK,KAAK,GAAG,YAClB,KAAK,MAAM,UAAU,KAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK,IAAI,CAAC,CACvE;CACF;CAEA,YAAY,MAA6B;EACvC,OAAO,KAAK,KAAK,GAAG,YAAY,KAAK,MAAM,YAAY,KAAK,UAAU,CAAC;CACzE;CAEA,MAAM,YACJ,MACA,EAAE,WAAW,cACiB;EAC9B,IAAI;GACF,MAAM,KAAK,KAAK,aAAa,MAAM;IAAE,MAAM;IAAiB,SAAS;GAAU,CAAC;GAChF,OAAO;EACT,SAAS,OAAO;GAWd,IAAI,MAHmB,KAAK,KAAK,GAAG,GAAG,KAAK,aAAa,YACvD,YAAY,YAAY,KAAK,IAAI,CAAC,CACpC,GACc,OAAO;GACrB,MAAM;EACR;CACF;AACF;;;;;;;AAQA,IAAa,gBAAb,cAAmC,mBAA8C;;;;;;;CAO/E,cAAsC;EACpC,OAAO,QAAQ,KAAK,GAAG;CACzB;;CAGA,MAAgB,WAAW,QAAqC,CAAC;CAEjE;;;;;;CAOA,UAAgC;EAC9B,OAAQ,KAAK,YAAY;GAAE,GAAG,KAAK;GAAK,SAAS,yBAAyB,KAAK,IAAI,OAAO;EAAE;CAC9F;;;;;;;;;;;;CAaA,QAAkB,SAA+C;EAC/D,OAAO,eAAe,KAAA,GAAW,YAAY;CAC/C;;;;;;CAOA,sBAA+C;EAC7C,OAAO,KAAK,IAAI,sBACZ,IAAI,qBAAqB,KAAK,IAAI,mBAAmB,IACrD,IAAI,iBAAiB;CAC3B;;;;;;;;CASA,UAAiD;EAC/C,OAAO,CAAC;CACV;;;;;CAMA,WAA2C,CAE3C;;;;;;CAOA,yBAAiE,CAEjE;;;;;CAMA,eAAyB,QAAmD,CAE5E;;CAGA,sBAA+C;EAC7C,OAAO,IAAI,sBAAsB,KAAK,QAAQ,CAAC;CACjD;;;;;CAMA,eAAyB,OAAqB,QAAwC;EACpF,OAAO;GACL;GACA,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ,MAAM;GAC5B,UAAU,KAAK,oBAAoB;GACnC,SAAS,KAAK,oBAAoB;GAClC,UAAU,KAAK,SAAS;GACxB,WAAW,KAAK,uBAAuB;GACvC,UAAU,KAAK,eAAe,KAAK;EACrC;CACF;CAEA,MAAM,IAAI,OAAqC,MAA6C;EAC1F,MAAM,QAAQ,KAAK,YAAY;EAC/B,IAAI;GACF,MAAM,EAAE,WAAW,MAAM;GACzB,OAAO,MAAM,eACX;IACE,YAAY,MAAM;IAClB,QAAQ,MAAM;IAEd,aAAa,MAAM,UAAU,QAAQ;IACrC,MAAM,IAAI,aAAa,MAAM,OAAO,QAAQ,MAAM,UAAU;GAC9D,GACA,KAAK,eAAe,OAAO,MAAM,OAAO,CAC1C;EACF,UAAU;GACR,MAAM,KAAK,WAAW,KAAK;EAC7B;CACF;AACF"}
1
+ {"version":3,"file":"runner.mjs","names":[],"sources":["../../src/cloudflare/runner.ts"],"sourcesContent":["import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from 'cloudflare:workers';\nimport { NonRetryableError } from 'cloudflare:workflows';\nimport type { Contract } from '../contract';\nimport { type RegisteredAction, RegistryActionInvoker } from '../engine/actions';\nimport type {\n ActionInvoker,\n EngineStep,\n JourneyObserver,\n JourneyOutcome,\n MessageSender,\n MessageValidator,\n} from '../engine/ports';\nimport { isRetryable } from '../engine/retry';\nimport { type JourneyRunParts, executeJourney } from '../host/execute';\nimport { type JourneyEnv, type JourneyParams, WAKE_EVENT_TYPE } from '../host/platform';\nimport { LogMessageSender, WebhookMessageSender } from '../host/senders';\nimport { type JourneyRuntimeOptions, resolveRuntime } from '../runtime';\nimport type { JourneyStore } from '../store/index';\nimport { cloudflareJourneyBinding, wakeExpired } from './bindings';\n\n/**\n * Adapts CF's WorkflowStep to EngineStep.\n * subscribe/unsubscribe write the subscription table inside durable steps (the\n * router wakes instances from that table); waitForWake parks on CF's\n * waitForEvent, which signals a timeout by throwing — and so does every other\n * failure in there, so only the clock, against the checkpointed deadline, can\n * tell them apart (see wakeExpired).\n */\nclass CfEngineStep implements EngineStep {\n constructor(\n private readonly step: WorkflowStep,\n private readonly store: JourneyStore,\n private readonly userId: string,\n private readonly instanceId: string\n ) {}\n\n /**\n * A failure a retry would only repeat (`isRetryable`: a template refusing its props, the\n * contract refusing an emitted event, a provider rejecting the request) ends the step at\n * once instead of burning the retry budget. The engine recognizes a NonRetryableError by its\n * `name`, so the original's name is not written over it — the original travels as `cause`.\n */\n do<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return this.step.do(name, async () => {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && !isRetryable(error)) {\n const permanent = new NonRetryableError(error.message);\n permanent.cause = error;\n throw permanent;\n }\n throw error;\n }\n });\n }\n\n sleep(name: string, ms: number): Promise<void> {\n return this.step.sleep(name, ms);\n }\n\n subscribe(name: string, events: readonly string[]): Promise<void> {\n // Idempotent in the store: the interpreter re-subscribes on every wait\n // attempt (one-shot-callback contract) and registrations persist here.\n return this.step.do(name, () =>\n this.store.subscribe(this.instanceId, this.userId, events, Date.now())\n );\n }\n\n unsubscribe(name: string): Promise<void> {\n return this.step.do(name, () => this.store.unsubscribe(this.instanceId));\n }\n\n async waitForWake(\n name: string,\n { timeoutMs, deadlineMs }: { timeoutMs: number; deadlineMs: number }\n ): Promise<'event' | 'timeout'> {\n try {\n await this.step.waitForEvent(name, { type: WAKE_EVENT_TYPE, timeout: timeoutMs });\n return 'event';\n } catch (error) {\n /*\n * Only the deadline can tell a real timeout from a failure (see wakeExpired). The\n * deadline is the interpreter's checkpoint, so the verdict is the same on the attempt\n * that parked and on a replay after an eviction — which is where the wait usually\n * resurfaces: the instance is rebuilt, the wait is already over, and the first thing to\n * run is this step. The verdict is checkpointed too, so later replays reuse it.\n */\n const timedOut = await this.step.do(`${name}:timed-out`, async () =>\n wakeExpired(deadlineMs, Date.now())\n );\n if (timedOut) return 'timeout';\n throw error;\n }\n }\n}\n\n/**\n * The generic journey executor: one class runs every workflow, because IR is\n * data. It is loaded from the store by the contentHash pinned at entry —\n * content addressing makes it immutable, so reading it outside a step is\n * replay-safe.\n */\nexport class JourneyRunner extends WorkflowEntrypoint<JourneyEnv, JourneyParams> {\n /**\n * The data plane: `journeyWorker` opens it through the host's store lease. A runner subclass\n * of its own overrides this (and `closeStore` if its client needs closing):\n *\n * protected override createStore() { return new PostgresJourneyStore(client(this.env)); }\n */\n protected createStore(): JourneyStore {\n throw new Error('JourneyRunner: override createStore, or build the runner with journeyWorker');\n }\n\n /** Called once `run` is over, success or not — release whatever `createStore` opened. */\n protected async closeStore(_store: JourneyStore): Promise<void> {}\n\n private adapted: JourneyEnv | undefined;\n\n /**\n * The env a run ingests its emitted events with: the Workflow binding behind the host's port,\n * so an instance the platform no longer knows answers `InstanceNotFoundError` (what lets the\n * host drop its wakes). Built once per instance.\n */\n protected hostEnv(): JourneyEnv {\n return (this.adapted ??= { ...this.env, JOURNEY: cloudflareJourneyBinding(this.env.JOURNEY) });\n }\n\n /**\n * Runtime options for this instance — typed configuration, resolved by the app (typically\n * `resolveRuntime(config.runtime, mode)` over its workflow.config.ts, with the mode coming from\n * an ENVIRONMENT var). The instance params are passed so the decision can also be per user:\n * a tester account in production can run in fast-forward while everyone else runs in real\n * time. Defaults: real time, quiet.\n *\n * protected override runtime({ userId }) {\n * return resolveRuntime(workflowConfig.runtime, isTester(userId) ? 'test' : this.env.ENVIRONMENT);\n * }\n */\n protected runtime(_params: JourneyParams): JourneyRuntimeOptions {\n return resolveRuntime(undefined, 'production');\n }\n\n /**\n * Message outlet; an app overrides this to plug in real channels (say\n * an EmailSender over a transport with a react-email renderer). By default it picks the webhook\n * or logging sender based on the environment.\n */\n protected createMessageSender(): MessageSender {\n return this.env.MESSAGE_WEBHOOK_URL\n ? new WebhookMessageSender(this.env.MESSAGE_WEBHOOK_URL)\n : new LogMessageSender();\n }\n\n /**\n * Custom-action registry; an app overrides this returning the same\n * `action(...)` objects its workflows reference (an ActionRef is a\n * RegisteredAction structurally) — the code plane of the dual-plane model:\n *\n * protected override actions() { return [syncCrm, issueCoupon]; }\n */\n protected actions(): readonly RegisteredAction[] {\n return [];\n }\n\n /**\n * The contract events this journey emits (`.sendEvent()`) are checked\n * against, exactly like ingest; journeyWorker passes its config's.\n */\n protected contract(): Contract | undefined {\n return undefined;\n }\n\n /**\n * Template props check before every send; an app overrides this with\n * `registryValidator({ emails, pushes })` (journeyWorker does it from its\n * registries). By default props go out as resolved.\n */\n protected createMessageValidator(): MessageValidator | undefined {\n return undefined;\n }\n\n /**\n * Reporting hooks: node arrivals, every copy sent, how each instance ended. The host stores\n * what it needs for its dashboards; by default nothing is reported.\n */\n protected createObserver(_store: JourneyStore): JourneyObserver | undefined {\n return undefined;\n }\n\n /** Override for a different version policy ('warn' by default) or a fully custom invoker (e.g. webhook degradation for hosted tenants). */\n protected createActionInvoker(): ActionInvoker {\n return new RegistryActionInvoker(this.actions());\n }\n\n /**\n * Everything one run is wired to. By default it is composed from the methods above; a host\n * that assembles the whole set itself (journeyWorker) overrides this one instead.\n */\n protected createRunParts(store: JourneyStore, params: JourneyParams): JourneyRunParts {\n return {\n store,\n env: this.hostEnv(),\n runtime: this.runtime(params),\n messages: this.createMessageSender(),\n actions: this.createActionInvoker(),\n contract: this.contract(),\n validator: this.createMessageValidator(),\n observer: this.createObserver(store),\n };\n }\n\n async run(event: WorkflowEvent<JourneyParams>, step: WorkflowStep): Promise<JourneyOutcome> {\n const store = this.createStore();\n try {\n const { userId } = event.payload;\n return await executeJourney(\n {\n instanceId: event.instanceId,\n params: event.payload,\n // Trigger-event creation time: replay-stable, unlike Date.now() here\n enteredAtMs: event.timestamp.getTime(),\n step: new CfEngineStep(step, store, userId, event.instanceId),\n },\n this.createRunParts(store, event.payload)\n );\n } finally {\n await this.closeStore(store);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,IAAM,eAAN,MAAyC;CAEpB;CACA;CACA;CACA;CAJnB,YACE,MACA,OACA,QACA,YACA;EAJiB,KAAA,OAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,aAAA;CAChB;;;;;;;CAQH,GAAM,MAAc,IAAkC;EACpD,OAAO,KAAK,KAAK,GAAG,MAAM,YAAY;GACpC,IAAI;IACF,OAAO,MAAM,GAAG;GAClB,SAAS,OAAO;IACd,IAAI,iBAAiB,SAAS,CAAC,YAAY,KAAK,GAAG;KACjD,MAAM,YAAY,IAAI,kBAAkB,MAAM,OAAO;KACrD,UAAU,QAAQ;KAClB,MAAM;IACR;IACA,MAAM;GACR;EACF,CAAC;CACH;CAEA,MAAM,MAAc,IAA2B;EAC7C,OAAO,KAAK,KAAK,MAAM,MAAM,EAAE;CACjC;CAEA,UAAU,MAAc,QAA0C;EAGhE,OAAO,KAAK,KAAK,GAAG,YAClB,KAAK,MAAM,UAAU,KAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK,IAAI,CAAC,CACvE;CACF;CAEA,YAAY,MAA6B;EACvC,OAAO,KAAK,KAAK,GAAG,YAAY,KAAK,MAAM,YAAY,KAAK,UAAU,CAAC;CACzE;CAEA,MAAM,YACJ,MACA,EAAE,WAAW,cACiB;EAC9B,IAAI;GACF,MAAM,KAAK,KAAK,aAAa,MAAM;IAAE,MAAM;IAAiB,SAAS;GAAU,CAAC;GAChF,OAAO;EACT,SAAS,OAAO;GAWd,IAAI,MAHmB,KAAK,KAAK,GAAG,GAAG,KAAK,aAAa,YACvD,YAAY,YAAY,KAAK,IAAI,CAAC,CACpC,GACc,OAAO;GACrB,MAAM;EACR;CACF;AACF;;;;;;;AAQA,IAAa,gBAAb,cAAmC,mBAA8C;;;;;;;CAO/E,cAAsC;EACpC,MAAM,IAAI,MAAM,6EAA6E;CAC/F;;CAGA,MAAgB,WAAW,QAAqC,CAAC;CAEjE;;;;;;CAOA,UAAgC;EAC9B,OAAQ,KAAK,YAAY;GAAE,GAAG,KAAK;GAAK,SAAS,yBAAyB,KAAK,IAAI,OAAO;EAAE;CAC9F;;;;;;;;;;;;CAaA,QAAkB,SAA+C;EAC/D,OAAO,eAAe,KAAA,GAAW,YAAY;CAC/C;;;;;;CAOA,sBAA+C;EAC7C,OAAO,KAAK,IAAI,sBACZ,IAAI,qBAAqB,KAAK,IAAI,mBAAmB,IACrD,IAAI,iBAAiB;CAC3B;;;;;;;;CASA,UAAiD;EAC/C,OAAO,CAAC;CACV;;;;;CAMA,WAA2C,CAE3C;;;;;;CAOA,yBAAiE,CAEjE;;;;;CAMA,eAAyB,QAAmD,CAE5E;;CAGA,sBAA+C;EAC7C,OAAO,IAAI,sBAAsB,KAAK,QAAQ,CAAC;CACjD;;;;;CAMA,eAAyB,OAAqB,QAAwC;EACpF,OAAO;GACL;GACA,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ,MAAM;GAC5B,UAAU,KAAK,oBAAoB;GACnC,SAAS,KAAK,oBAAoB;GAClC,UAAU,KAAK,SAAS;GACxB,WAAW,KAAK,uBAAuB;GACvC,UAAU,KAAK,eAAe,KAAK;EACrC;CACF;CAEA,MAAM,IAAI,OAAqC,MAA6C;EAC1F,MAAM,QAAQ,KAAK,YAAY;EAC/B,IAAI;GACF,MAAM,EAAE,WAAW,MAAM;GACzB,OAAO,MAAM,eACX;IACE,YAAY,MAAM;IAClB,QAAQ,MAAM;IAEd,aAAa,MAAM,UAAU,QAAQ;IACrC,MAAM,IAAI,aAAa,MAAM,OAAO,QAAQ,MAAM,UAAU;GAC9D,GACA,KAAK,eAAe,OAAO,MAAM,OAAO,CAC1C;EACF,UAAU;GACR,MAAM,KAAK,WAAW,KAAK;EAC7B;CACF;AACF"}
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_host_journey_host = require("../host/journey-host.cjs");
3
3
  const require_cloudflare_bindings = require("./bindings.cjs");
4
4
  const require_cloudflare_runner = require("./runner.cjs");
5
- //#region src/cloudflare/worker.ts
5
+ // src/cloudflare/worker.ts
6
6
  /**
7
7
  * A complete journey host in one call: the runner class with the app's store,
8
8
  * outlets and runtime plugged in, and the fetch handler that serves the ingest
@@ -89,7 +89,6 @@ function journeyWorker(options) {
89
89
  scheduled
90
90
  };
91
91
  }
92
- //#endregion
93
92
  exports.EnvValidationError = require_host_journey_host.EnvValidationError;
94
93
  exports.journeyWorker = journeyWorker;
95
94
 
@@ -2,7 +2,6 @@ import { JourneyEnv } from "../host/platform.cjs";
2
2
  import { SweepResult } from "../host/ingest.cjs";
3
3
  import { EnvValidationError, JourneyHostOptions } from "../host/journey-host.cjs";
4
4
  import { JourneyRunner } from "./runner.cjs";
5
- //#region src/cloudflare/worker.d.ts
6
5
  /** The fetch handler's execution context (the subset used). */
7
6
  export interface ExecutionContextLike {
8
7
  waitUntil(promise: Promise<unknown>): void;
@@ -41,6 +40,5 @@ export interface JourneyWorker<Env extends JourneyEnv> {
41
40
  * export default { fetch: journeys.fetch };
42
41
  */
43
42
  export declare function journeyWorker<Env extends JourneyEnv>(options: JourneyWorkerOptions<Env>): JourneyWorker<Env>;
44
- //#endregion
45
43
  export { EnvValidationError };
46
44
  //# sourceMappingURL=worker.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.cts","names":[],"sources":["../../src/cloudflare/worker.ts"],"mappings":";;;;;;iBAeiB;EACf,UAAU,SAAS;;;;;;;YAQT,qBAAqB,YAAY,cAAc,mBAAmB;iBAE7D,cAAc,YAAY;;EAEzC,gBAAgB,kBAAkB;;EAElC,QAAQ,SAAS,SAAS,KAAK,KAAK,MAAM,yBAAyB,QAAQ;;;;;;;EAO3E,QAAQ,KAAK,QAAQ,QAAQ;;EAE7B,YAAY,qBAAqB,KAAK,KAAK,KAAK,yBAAyB;;;;;;;;;;;;;;wBAe3D,cAAc,YAAY,YACxC,SAAS,qBAAqB,OAC7B,cAAc"}
1
+ {"version":3,"file":"worker.d.cts","names":[],"sources":["../../src/cloudflare/worker.ts"],"mappings":";;;;;iBAeiB;EACf,UAAU,SAAS;;;;;;;YAQT,qBAAqB,YAAY,cAAc,mBAAmB;iBAE7D,cAAc,YAAY;;EAEzC,gBAAgB,kBAAkB;;EAElC,QAAQ,SAAS,SAAS,KAAK,KAAK,MAAM,yBAAyB,QAAQ;;;;;;;EAO3E,QAAQ,KAAK,QAAQ,QAAQ;;EAE7B,YAAY,qBAAqB,KAAK,KAAK,KAAK,yBAAyB;;;;;;;;;;;;;;wBAe3D,cAAc,YAAY,YACxC,SAAS,qBAAqB,OAC7B,cAAc"}