@shware/workflow 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/README.md +165 -42
  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 +2 -3
  28. package/dist/aws/index.d.cts +0 -2
  29. package/dist/aws/index.d.cts.map +1 -1
  30. package/dist/aws/index.d.mts +0 -2
  31. package/dist/aws/index.d.mts.map +1 -1
  32. package/dist/aws/index.mjs +2 -3
  33. package/dist/aws/instances.cjs +1 -2
  34. package/dist/aws/instances.d.cts +0 -2
  35. package/dist/aws/instances.d.cts.map +1 -1
  36. package/dist/aws/instances.d.mts +0 -2
  37. package/dist/aws/instances.d.mts.map +1 -1
  38. package/dist/aws/instances.mjs +1 -2
  39. package/dist/aws/lambda-api.cjs +1 -2
  40. package/dist/aws/lambda-api.d.cts +0 -2
  41. package/dist/aws/lambda-api.d.cts.map +1 -1
  42. package/dist/aws/lambda-api.d.mts +0 -2
  43. package/dist/aws/lambda-api.d.mts.map +1 -1
  44. package/dist/aws/lambda-api.mjs +1 -2
  45. package/dist/client.cjs +46 -6
  46. package/dist/client.cjs.map +1 -1
  47. package/dist/client.d.cts +25 -5
  48. package/dist/client.d.cts.map +1 -1
  49. package/dist/client.d.mts +25 -5
  50. package/dist/client.d.mts.map +1 -1
  51. package/dist/client.mjs +46 -6
  52. package/dist/client.mjs.map +1 -1
  53. package/dist/cloudflare/bindings.cjs +1 -2
  54. package/dist/cloudflare/bindings.d.cts +0 -2
  55. package/dist/cloudflare/bindings.d.cts.map +1 -1
  56. package/dist/cloudflare/bindings.d.mts +0 -2
  57. package/dist/cloudflare/bindings.d.mts.map +1 -1
  58. package/dist/cloudflare/bindings.mjs +1 -2
  59. package/dist/cloudflare/index.cjs +2 -2
  60. package/dist/cloudflare/index.mjs +2 -2
  61. package/dist/cloudflare/runner.cjs +2 -3
  62. package/dist/cloudflare/runner.d.cts +1 -3
  63. package/dist/cloudflare/runner.d.cts.map +1 -1
  64. package/dist/cloudflare/runner.d.mts +1 -3
  65. package/dist/cloudflare/runner.d.mts.map +1 -1
  66. package/dist/cloudflare/runner.mjs +2 -3
  67. package/dist/cloudflare/worker.cjs +1 -2
  68. package/dist/cloudflare/worker.d.cts +0 -2
  69. package/dist/cloudflare/worker.d.cts.map +1 -1
  70. package/dist/cloudflare/worker.d.mts +0 -2
  71. package/dist/cloudflare/worker.d.mts.map +1 -1
  72. package/dist/cloudflare/worker.mjs +1 -2
  73. package/dist/cloudflare/workers.d.cts +0 -2
  74. package/dist/cloudflare/workers.d.cts.map +1 -1
  75. package/dist/cloudflare/workers.d.mts +0 -2
  76. package/dist/cloudflare/workers.d.mts.map +1 -1
  77. package/dist/config.cjs +25 -5
  78. package/dist/config.cjs.map +1 -1
  79. package/dist/config.d.cts +15 -11
  80. package/dist/config.d.cts.map +1 -1
  81. package/dist/config.d.mts +15 -11
  82. package/dist/config.d.mts.map +1 -1
  83. package/dist/config.mjs +26 -6
  84. package/dist/config.mjs.map +1 -1
  85. package/dist/contract.cjs +12 -2
  86. package/dist/contract.cjs.map +1 -1
  87. package/dist/contract.d.cts +28 -9
  88. package/dist/contract.d.cts.map +1 -1
  89. package/dist/contract.d.mts +28 -9
  90. package/dist/contract.d.mts.map +1 -1
  91. package/dist/contract.mjs +12 -2
  92. package/dist/contract.mjs.map +1 -1
  93. package/dist/dsl/action.cjs +1 -2
  94. package/dist/dsl/action.d.cts +0 -2
  95. package/dist/dsl/action.d.cts.map +1 -1
  96. package/dist/dsl/action.d.mts +0 -2
  97. package/dist/dsl/action.d.mts.map +1 -1
  98. package/dist/dsl/action.mjs +1 -2
  99. package/dist/dsl/base.cjs +1 -2
  100. package/dist/dsl/base.d.cts +0 -2
  101. package/dist/dsl/base.d.cts.map +1 -1
  102. package/dist/dsl/base.d.mts +0 -2
  103. package/dist/dsl/base.d.mts.map +1 -1
  104. package/dist/dsl/base.mjs +1 -2
  105. package/dist/dsl/bundle.cjs +5 -5
  106. package/dist/dsl/bundle.cjs.map +1 -1
  107. package/dist/dsl/bundle.d.cts +5 -3
  108. package/dist/dsl/bundle.d.cts.map +1 -1
  109. package/dist/dsl/bundle.d.mts +5 -3
  110. package/dist/dsl/bundle.d.mts.map +1 -1
  111. package/dist/dsl/bundle.mjs +5 -5
  112. package/dist/dsl/bundle.mjs.map +1 -1
  113. package/dist/dsl/condition.cjs +1 -2
  114. package/dist/dsl/condition.d.cts +0 -2
  115. package/dist/dsl/condition.d.cts.map +1 -1
  116. package/dist/dsl/condition.d.mts +0 -2
  117. package/dist/dsl/condition.d.mts.map +1 -1
  118. package/dist/dsl/condition.mjs +1 -2
  119. package/dist/dsl/flow.cjs +3 -3
  120. package/dist/dsl/flow.cjs.map +1 -1
  121. package/dist/dsl/flow.d.cts +1 -3
  122. package/dist/dsl/flow.d.cts.map +1 -1
  123. package/dist/dsl/flow.d.mts +1 -3
  124. package/dist/dsl/flow.d.mts.map +1 -1
  125. package/dist/dsl/flow.mjs +3 -3
  126. package/dist/dsl/flow.mjs.map +1 -1
  127. package/dist/dsl/refs.cjs +1 -2
  128. package/dist/dsl/refs.d.cts +0 -2
  129. package/dist/dsl/refs.d.cts.map +1 -1
  130. package/dist/dsl/refs.d.mts +0 -2
  131. package/dist/dsl/refs.d.mts.map +1 -1
  132. package/dist/dsl/refs.mjs +1 -2
  133. package/dist/dsl/template.cjs +1 -2
  134. package/dist/dsl/template.d.cts +0 -2
  135. package/dist/dsl/template.d.cts.map +1 -1
  136. package/dist/dsl/template.d.mts +0 -2
  137. package/dist/dsl/template.d.mts.map +1 -1
  138. package/dist/dsl/template.mjs +1 -2
  139. package/dist/dsl/trigger.cjs +1 -2
  140. package/dist/dsl/trigger.d.cts +0 -2
  141. package/dist/dsl/trigger.d.cts.map +1 -1
  142. package/dist/dsl/trigger.d.mts +0 -2
  143. package/dist/dsl/trigger.d.mts.map +1 -1
  144. package/dist/dsl/trigger.mjs +1 -2
  145. package/dist/dsl/workflow.cjs +3 -4
  146. package/dist/dsl/workflow.d.cts +0 -2
  147. package/dist/dsl/workflow.d.cts.map +1 -1
  148. package/dist/dsl/workflow.d.mts +0 -2
  149. package/dist/dsl/workflow.d.mts.map +1 -1
  150. package/dist/dsl/workflow.mjs +3 -4
  151. package/dist/email-context.cjs +1 -2
  152. package/dist/email-context.d.cts +0 -2
  153. package/dist/email-context.d.cts.map +1 -1
  154. package/dist/email-context.d.mts +0 -2
  155. package/dist/email-context.d.mts.map +1 -1
  156. package/dist/email-context.mjs +1 -2
  157. package/dist/email-sender.cjs +2 -3
  158. package/dist/email-sender.cjs.map +1 -1
  159. package/dist/email-sender.d.cts +1 -3
  160. package/dist/email-sender.d.cts.map +1 -1
  161. package/dist/email-sender.d.mts +1 -3
  162. package/dist/email-sender.d.mts.map +1 -1
  163. package/dist/email-sender.mjs +2 -3
  164. package/dist/email-sender.mjs.map +1 -1
  165. package/dist/email.cjs +33 -7
  166. package/dist/email.cjs.map +1 -1
  167. package/dist/email.d.cts +38 -11
  168. package/dist/email.d.cts.map +1 -1
  169. package/dist/email.d.mts +38 -11
  170. package/dist/email.d.mts.map +1 -1
  171. package/dist/email.mjs +33 -8
  172. package/dist/email.mjs.map +1 -1
  173. package/dist/engine/actions.cjs +1 -2
  174. package/dist/engine/actions.d.cts +0 -2
  175. package/dist/engine/actions.d.cts.map +1 -1
  176. package/dist/engine/actions.d.mts +0 -2
  177. package/dist/engine/actions.d.mts.map +1 -1
  178. package/dist/engine/actions.mjs +1 -2
  179. package/dist/engine/bucket.cjs +1 -2
  180. package/dist/engine/bucket.d.cts +0 -2
  181. package/dist/engine/bucket.d.cts.map +1 -1
  182. package/dist/engine/bucket.d.mts +0 -2
  183. package/dist/engine/bucket.d.mts.map +1 -1
  184. package/dist/engine/bucket.mjs +1 -2
  185. package/dist/engine/condition.cjs +1 -2
  186. package/dist/engine/condition.cjs.map +1 -1
  187. package/dist/engine/condition.d.cts +0 -2
  188. package/dist/engine/condition.d.cts.map +1 -1
  189. package/dist/engine/condition.d.mts +0 -2
  190. package/dist/engine/condition.d.mts.map +1 -1
  191. package/dist/engine/condition.mjs +1 -2
  192. package/dist/engine/condition.mjs.map +1 -1
  193. package/dist/engine/duration.cjs +1 -2
  194. package/dist/engine/duration.d.cts +0 -2
  195. package/dist/engine/duration.d.cts.map +1 -1
  196. package/dist/engine/duration.d.mts +0 -2
  197. package/dist/engine/duration.d.mts.map +1 -1
  198. package/dist/engine/duration.mjs +1 -2
  199. package/dist/engine/index.cjs +1 -1
  200. package/dist/engine/index.mjs +1 -1
  201. package/dist/engine/interpreter.cjs +22 -6
  202. package/dist/engine/interpreter.cjs.map +1 -1
  203. package/dist/engine/interpreter.d.cts +0 -2
  204. package/dist/engine/interpreter.d.cts.map +1 -1
  205. package/dist/engine/interpreter.d.mts +0 -2
  206. package/dist/engine/interpreter.d.mts.map +1 -1
  207. package/dist/engine/interpreter.mjs +22 -6
  208. package/dist/engine/interpreter.mjs.map +1 -1
  209. package/dist/engine/ports.d.cts +8 -4
  210. package/dist/engine/ports.d.cts.map +1 -1
  211. package/dist/engine/ports.d.mts +8 -4
  212. package/dist/engine/ports.d.mts.map +1 -1
  213. package/dist/engine/recipient.cjs +1 -2
  214. package/dist/engine/recipient.d.cts +0 -2
  215. package/dist/engine/recipient.d.cts.map +1 -1
  216. package/dist/engine/recipient.d.mts +0 -2
  217. package/dist/engine/recipient.d.mts.map +1 -1
  218. package/dist/engine/recipient.mjs +1 -2
  219. package/dist/engine/retry.cjs +1 -2
  220. package/dist/engine/retry.d.cts +0 -2
  221. package/dist/engine/retry.d.cts.map +1 -1
  222. package/dist/engine/retry.d.mts +0 -2
  223. package/dist/engine/retry.d.mts.map +1 -1
  224. package/dist/engine/retry.mjs +1 -2
  225. package/dist/engine/time-scale.cjs +1 -2
  226. package/dist/engine/time-scale.d.cts +0 -2
  227. package/dist/engine/time-scale.d.cts.map +1 -1
  228. package/dist/engine/time-scale.d.mts +0 -2
  229. package/dist/engine/time-scale.d.mts.map +1 -1
  230. package/dist/engine/time-scale.mjs +1 -2
  231. package/dist/engine/time-window.cjs +1 -2
  232. package/dist/engine/time-window.d.cts +0 -2
  233. package/dist/engine/time-window.d.cts.map +1 -1
  234. package/dist/engine/time-window.d.mts +0 -2
  235. package/dist/engine/time-window.d.mts.map +1 -1
  236. package/dist/engine/time-window.mjs +1 -2
  237. package/dist/fcm.cjs +1 -2
  238. package/dist/fcm.d.cts +0 -2
  239. package/dist/fcm.d.cts.map +1 -1
  240. package/dist/fcm.d.mts +0 -2
  241. package/dist/fcm.d.mts.map +1 -1
  242. package/dist/fcm.mjs +1 -2
  243. package/dist/hash.cjs +1 -2
  244. package/dist/hash.d.cts +0 -2
  245. package/dist/hash.d.cts.map +1 -1
  246. package/dist/hash.d.mts +0 -2
  247. package/dist/hash.d.mts.map +1 -1
  248. package/dist/hash.mjs +1 -2
  249. package/dist/host/auth.cjs +1 -2
  250. package/dist/host/auth.d.cts +0 -2
  251. package/dist/host/auth.d.cts.map +1 -1
  252. package/dist/host/auth.d.mts +0 -2
  253. package/dist/host/auth.d.mts.map +1 -1
  254. package/dist/host/auth.mjs +1 -2
  255. package/dist/host/channels.cjs +2 -3
  256. package/dist/host/channels.d.cts +0 -2
  257. package/dist/host/channels.d.cts.map +1 -1
  258. package/dist/host/channels.d.mts +0 -2
  259. package/dist/host/channels.d.mts.map +1 -1
  260. package/dist/host/channels.mjs +2 -3
  261. package/dist/host/execute.cjs +3 -4
  262. package/dist/host/execute.d.cts +1 -3
  263. package/dist/host/execute.d.cts.map +1 -1
  264. package/dist/host/execute.d.mts +1 -3
  265. package/dist/host/execute.d.mts.map +1 -1
  266. package/dist/host/execute.mjs +3 -4
  267. package/dist/host/fresh-read.cjs +1 -2
  268. package/dist/host/fresh-read.d.cts +0 -2
  269. package/dist/host/fresh-read.d.cts.map +1 -1
  270. package/dist/host/fresh-read.d.mts +0 -2
  271. package/dist/host/fresh-read.d.mts.map +1 -1
  272. package/dist/host/fresh-read.mjs +1 -2
  273. package/dist/host/http.cjs +39 -5
  274. package/dist/host/http.cjs.map +1 -1
  275. package/dist/host/http.d.cts +2 -4
  276. package/dist/host/http.d.cts.map +1 -1
  277. package/dist/host/http.d.mts +2 -4
  278. package/dist/host/http.d.mts.map +1 -1
  279. package/dist/host/http.mjs +40 -6
  280. package/dist/host/http.mjs.map +1 -1
  281. package/dist/host/ingest.cjs +129 -6
  282. package/dist/host/ingest.cjs.map +1 -1
  283. package/dist/host/ingest.d.cts +71 -2
  284. package/dist/host/ingest.d.cts.map +1 -1
  285. package/dist/host/ingest.d.mts +71 -2
  286. package/dist/host/ingest.d.mts.map +1 -1
  287. package/dist/host/ingest.mjs +126 -7
  288. package/dist/host/ingest.mjs.map +1 -1
  289. package/dist/host/journey-host.cjs +11 -10
  290. package/dist/host/journey-host.cjs.map +1 -1
  291. package/dist/host/journey-host.d.cts +0 -2
  292. package/dist/host/journey-host.d.cts.map +1 -1
  293. package/dist/host/journey-host.d.mts +0 -2
  294. package/dist/host/journey-host.d.mts.map +1 -1
  295. package/dist/host/journey-host.mjs +11 -10
  296. package/dist/host/journey-host.mjs.map +1 -1
  297. package/dist/host/platform.cjs +1 -2
  298. package/dist/host/platform.d.cts +0 -2
  299. package/dist/host/platform.d.cts.map +1 -1
  300. package/dist/host/platform.d.mts +0 -2
  301. package/dist/host/platform.d.mts.map +1 -1
  302. package/dist/host/platform.mjs +1 -2
  303. package/dist/host/senders.cjs +1 -2
  304. package/dist/host/senders.d.cts +0 -2
  305. package/dist/host/senders.d.cts.map +1 -1
  306. package/dist/host/senders.d.mts +0 -2
  307. package/dist/host/senders.d.mts.map +1 -1
  308. package/dist/host/senders.mjs +1 -2
  309. package/dist/http2-client.cjs +1 -2
  310. package/dist/http2-client.d.cts +0 -2
  311. package/dist/http2-client.d.cts.map +1 -1
  312. package/dist/http2-client.d.mts +0 -2
  313. package/dist/http2-client.d.mts.map +1 -1
  314. package/dist/http2-client.mjs +1 -2
  315. package/dist/index.cjs +5 -2
  316. package/dist/index.d.cts +5 -5
  317. package/dist/index.d.mts +5 -5
  318. package/dist/index.mjs +5 -5
  319. package/dist/ir.cjs +12 -4
  320. package/dist/ir.cjs.map +1 -1
  321. package/dist/ir.d.cts +17 -2
  322. package/dist/ir.d.cts.map +1 -1
  323. package/dist/ir.d.mts +17 -2
  324. package/dist/ir.d.mts.map +1 -1
  325. package/dist/ir.mjs +12 -5
  326. package/dist/ir.mjs.map +1 -1
  327. package/dist/jwt.cjs +1 -2
  328. package/dist/jwt.d.cts +0 -2
  329. package/dist/jwt.d.cts.map +1 -1
  330. package/dist/jwt.d.mts +0 -2
  331. package/dist/jwt.d.mts.map +1 -1
  332. package/dist/jwt.mjs +1 -2
  333. package/dist/plan.cjs +1 -2
  334. package/dist/plan.d.cts +0 -2
  335. package/dist/plan.d.cts.map +1 -1
  336. package/dist/plan.d.mts +0 -2
  337. package/dist/plan.d.mts.map +1 -1
  338. package/dist/plan.mjs +1 -2
  339. package/dist/postgres-js.cjs +1 -2
  340. package/dist/postgres-js.d.cts +0 -2
  341. package/dist/postgres-js.d.cts.map +1 -1
  342. package/dist/postgres-js.d.mts +0 -2
  343. package/dist/postgres-js.d.mts.map +1 -1
  344. package/dist/postgres-js.mjs +1 -2
  345. package/dist/provenance.cjs +1 -2
  346. package/dist/provenance.d.cts +0 -2
  347. package/dist/provenance.d.cts.map +1 -1
  348. package/dist/provenance.d.mts +0 -2
  349. package/dist/provenance.d.mts.map +1 -1
  350. package/dist/provenance.mjs +1 -2
  351. package/dist/push.cjs +1 -2
  352. package/dist/push.d.cts +0 -2
  353. package/dist/push.d.cts.map +1 -1
  354. package/dist/push.d.mts +0 -2
  355. package/dist/push.d.mts.map +1 -1
  356. package/dist/push.mjs +1 -2
  357. package/dist/react-email.cjs +1 -2
  358. package/dist/react-email.d.cts +0 -2
  359. package/dist/react-email.d.cts.map +1 -1
  360. package/dist/react-email.d.mts +0 -2
  361. package/dist/react-email.d.mts.map +1 -1
  362. package/dist/react-email.mjs +1 -2
  363. package/dist/reporting/classify.cjs +1 -2
  364. package/dist/reporting/classify.d.cts +0 -2
  365. package/dist/reporting/classify.d.cts.map +1 -1
  366. package/dist/reporting/classify.d.mts +0 -2
  367. package/dist/reporting/classify.d.mts.map +1 -1
  368. package/dist/reporting/classify.mjs +1 -2
  369. package/dist/reporting/observer.cjs +2 -2
  370. package/dist/reporting/observer.cjs.map +1 -1
  371. package/dist/reporting/observer.d.cts +0 -2
  372. package/dist/reporting/observer.d.cts.map +1 -1
  373. package/dist/reporting/observer.d.mts +0 -2
  374. package/dist/reporting/observer.d.mts.map +1 -1
  375. package/dist/reporting/observer.mjs +2 -2
  376. package/dist/reporting/observer.mjs.map +1 -1
  377. package/dist/reporting/tracking.cjs +29 -12
  378. package/dist/reporting/tracking.cjs.map +1 -1
  379. package/dist/reporting/tracking.d.cts +13 -8
  380. package/dist/reporting/tracking.d.cts.map +1 -1
  381. package/dist/reporting/tracking.d.mts +13 -8
  382. package/dist/reporting/tracking.d.mts.map +1 -1
  383. package/dist/reporting/tracking.mjs +29 -12
  384. package/dist/reporting/tracking.mjs.map +1 -1
  385. package/dist/runtime.cjs +1 -2
  386. package/dist/runtime.d.cts +0 -2
  387. package/dist/runtime.d.cts.map +1 -1
  388. package/dist/runtime.d.mts +0 -2
  389. package/dist/runtime.d.mts.map +1 -1
  390. package/dist/runtime.mjs +1 -2
  391. package/dist/store/erasure.cjs +1 -2
  392. package/dist/store/erasure.d.cts +0 -2
  393. package/dist/store/erasure.d.cts.map +1 -1
  394. package/dist/store/erasure.d.mts +0 -2
  395. package/dist/store/erasure.d.mts.map +1 -1
  396. package/dist/store/erasure.mjs +1 -2
  397. package/dist/store/facts.cjs +4 -5
  398. package/dist/store/facts.cjs.map +1 -1
  399. package/dist/store/facts.d.cts +2 -4
  400. package/dist/store/facts.d.cts.map +1 -1
  401. package/dist/store/facts.d.mts +2 -4
  402. package/dist/store/facts.d.mts.map +1 -1
  403. package/dist/store/facts.mjs +4 -5
  404. package/dist/store/facts.mjs.map +1 -1
  405. package/dist/store/index.cjs +2 -3
  406. package/dist/store/index.cjs.map +1 -1
  407. package/dist/store/index.d.cts +44 -15
  408. package/dist/store/index.d.cts.map +1 -1
  409. package/dist/store/index.d.mts +44 -15
  410. package/dist/store/index.d.mts.map +1 -1
  411. package/dist/store/index.mjs +2 -3
  412. package/dist/store/index.mjs.map +1 -1
  413. package/dist/store/postgres-reporting.cjs +31 -12
  414. package/dist/store/postgres-reporting.cjs.map +1 -1
  415. package/dist/store/postgres-reporting.d.cts +4 -4
  416. package/dist/store/postgres-reporting.d.cts.map +1 -1
  417. package/dist/store/postgres-reporting.d.mts +4 -4
  418. package/dist/store/postgres-reporting.d.mts.map +1 -1
  419. package/dist/store/postgres-reporting.mjs +31 -12
  420. package/dist/store/postgres-reporting.mjs.map +1 -1
  421. package/dist/store/postgres.cjs +40 -5
  422. package/dist/store/postgres.cjs.map +1 -1
  423. package/dist/store/postgres.d.cts +4 -4
  424. package/dist/store/postgres.d.cts.map +1 -1
  425. package/dist/store/postgres.d.mts +4 -4
  426. package/dist/store/postgres.d.mts.map +1 -1
  427. package/dist/store/postgres.mjs +41 -6
  428. package/dist/store/postgres.mjs.map +1 -1
  429. package/dist/store/sql.cjs +1 -2
  430. package/dist/store/sql.d.cts +0 -2
  431. package/dist/store/sql.d.cts.map +1 -1
  432. package/dist/store/sql.d.mts +0 -2
  433. package/dist/store/sql.d.mts.map +1 -1
  434. package/dist/store/sql.mjs +1 -2
  435. package/dist/store/tables.cjs +76 -13
  436. package/dist/store/tables.cjs.map +1 -1
  437. package/dist/store/tables.d.cts +17 -3
  438. package/dist/store/tables.d.cts.map +1 -1
  439. package/dist/store/tables.d.mts +17 -3
  440. package/dist/store/tables.d.mts.map +1 -1
  441. package/dist/store/tables.mjs +75 -14
  442. package/dist/store/tables.mjs.map +1 -1
  443. package/dist/store/user-lock.cjs +1 -2
  444. package/dist/store/user-lock.d.cts +0 -2
  445. package/dist/store/user-lock.d.cts.map +1 -1
  446. package/dist/store/user-lock.d.mts +0 -2
  447. package/dist/store/user-lock.d.mts.map +1 -1
  448. package/dist/store/user-lock.mjs +1 -2
  449. package/dist/templates.cjs +61 -9
  450. package/dist/templates.cjs.map +1 -1
  451. package/dist/templates.d.cts +101 -15
  452. package/dist/templates.d.cts.map +1 -1
  453. package/dist/templates.d.mts +101 -15
  454. package/dist/templates.d.mts.map +1 -1
  455. package/dist/templates.mjs +62 -11
  456. package/dist/templates.mjs.map +1 -1
  457. package/dist/transports/cloudflare-email.cjs +1 -2
  458. package/dist/transports/cloudflare-email.d.cts +0 -2
  459. package/dist/transports/cloudflare-email.d.cts.map +1 -1
  460. package/dist/transports/cloudflare-email.d.mts +0 -2
  461. package/dist/transports/cloudflare-email.d.mts.map +1 -1
  462. package/dist/transports/cloudflare-email.mjs +1 -2
  463. package/dist/transports/ses.cjs +1 -2
  464. package/dist/transports/ses.d.cts +0 -2
  465. package/dist/transports/ses.d.cts.map +1 -1
  466. package/dist/transports/ses.d.mts +0 -2
  467. package/dist/transports/ses.d.mts.map +1 -1
  468. package/dist/transports/ses.mjs +1 -2
  469. package/dist/transports/sigv4.cjs +1 -2
  470. package/dist/transports/sigv4.d.cts +0 -2
  471. package/dist/transports/sigv4.d.cts.map +1 -1
  472. package/dist/transports/sigv4.d.mts +0 -2
  473. package/dist/transports/sigv4.d.mts.map +1 -1
  474. package/dist/transports/sigv4.mjs +1 -2
  475. package/dist/webhooks.cjs +1 -2
  476. package/dist/webhooks.d.cts +0 -2
  477. package/dist/webhooks.d.cts.map +1 -1
  478. package/dist/webhooks.d.mts +0 -2
  479. package/dist/webhooks.d.mts.map +1 -1
  480. package/dist/webhooks.mjs +1 -2
  481. package/dist/webpush.cjs +1 -2
  482. package/dist/webpush.d.cts +0 -2
  483. package/dist/webpush.d.cts.map +1 -1
  484. package/dist/webpush.d.mts +0 -2
  485. package/dist/webpush.d.mts.map +1 -1
  486. package/dist/webpush.mjs +1 -2
  487. package/package.json +5 -5
package/README.md CHANGED
@@ -54,6 +54,7 @@ export const contract = defineContract({
54
54
  purchase: looseObject({ transaction_id: string(), currency: string(), value: number() }),
55
55
  },
56
56
  profile: strictObject({ email: optional(email()), name: string() }),
57
+ subscriptions: { topics: ['promotions', 'newsletter', 'tips'] },
57
58
  });
58
59
 
59
60
  /** The DSL's reference tables: `e.login`, `u.name`. */
@@ -66,6 +67,16 @@ The profile is a flat object of string, number, boolean, enum and literal
66
67
  fields. Defaults, transforms, coercion and custom refinements are refused when
67
68
  the contract is defined, because input and output must mean the same JSON.
68
69
 
70
+ `subscriptions.topics` lists the subscription topics: content categories
71
+ ("offers", "tips"), not channels — ids only (a plain token; the app's i18n gives
72
+ them names). A plain array literal is enough: `defineContract` keeps the
73
+ literals, and the union they form types every email and push template's
74
+ `topic`, the config and `JourneyClient.setSubscriptions`. A user opts out of a
75
+ topic per channel (the preference page is topic × channel), or of a whole
76
+ channel; the engine keeps that record and is the one source of truth for it
77
+ (see [Email](#email), [Push](#push) and [`JourneyClient`](#journeyclient)).
78
+ Leave the field out when every email and push is transactional.
79
+
69
80
  ### 2. Templates
70
81
 
71
82
  One object per template, identified by its own `id` (unique per channel): the
@@ -74,14 +85,20 @@ stable and rename `title` instead. Its strict Zod `props` schema is the only
74
85
  source of the props type: the DSL's arguments, the `preview` and the component
75
86
  are all derived from it, and every send parses the props against it first.
76
87
 
88
+ ```ts
89
+ // src/contract.ts (continued): the template factories bound to the contract
90
+ export const { emailTemplate, pushTemplate } = templatesFor(contract);
91
+ ```
92
+
77
93
  ```tsx
78
94
  // src/email/welcome.tsx
79
95
  import { Html, Text } from '@react-email/components';
80
- import { emailTemplate } from '@shware/workflow';
81
96
  import { strictObject, string } from 'zod/mini';
97
+ import { emailTemplate } from '../contract';
82
98
 
83
99
  export default emailTemplate({
84
100
  id: 'welcome',
101
+ transactional: true,
85
102
  from: { email: 'noreply@acme.test', name: 'Acme' },
86
103
  title: 'Welcome',
87
104
  props: strictObject({ name: string() }),
@@ -95,6 +112,17 @@ export default emailTemplate({
95
112
  });
96
113
  ```
97
114
 
115
+ Every email and push template says what it is: `topic: 'tips'` (a topic the
116
+ contract declares, which the user can opt out of on that channel) or
117
+ `transactional: true` (a receipt, a code, an invite: sent whatever they opted
118
+ out of; for an email, with no unsubscribe link). Leaving both out, or giving
119
+ both, is a type error and a compile error, and the error says so in words.
120
+ `templatesFor(contract)` gives the factories with the topic typed by the
121
+ contract, so a topic it does not declare is an error at the template's own
122
+ `topic` line, in the editor and when the module loads; the bare `emailTemplate`
123
+ / `pushTemplate` from `@shware/workflow` are for a project without a contract
124
+ (transactional templates only), and the compile checks every template again.
125
+
98
126
  Gather them per channel; the workflows send the definitions and the config
99
127
  registers the whole:
100
128
 
@@ -113,11 +141,13 @@ import { email } from './email';
113
141
  export const templates = { email };
114
142
  ```
115
143
 
116
- `tip.tsx` is written the same way. The property names are JavaScript names
117
- only. `.email(email.welcome, props)` checks `props` against that template's
118
- schema, and a push template is not accepted where an email is. The compile
119
- refuses an id registered twice in a channel, and a workflow sending a
120
- definition other than the one registered under its id.
144
+ `tip.tsx` is written the same way, with `topic: 'tips'`, and so is a
145
+ `pushTemplate`. The property names are JavaScript names only. `.email(email.welcome, props)` checks `props`
146
+ against that template's schema, and a push template is not accepted where an
147
+ email is. The compile refuses an id registered twice in a channel, a workflow
148
+ sending a definition other than the one registered under its id, and a topic
149
+ the contract does not declare (with a `contract` in the config, the editor
150
+ refuses it first).
121
151
 
122
152
  ### 3. A workflow
123
153
 
@@ -463,30 +493,42 @@ the compile fails.
463
493
 
464
494
  ### Email
465
495
 
466
- `emailTemplate({ id, from, replyTo?, unsubscribeUrl?, title, description?, props, subject, preview, component })`
496
+ `emailTemplate({ id, topic | transactional, from, replyTo?, unsubscribeUrl?, title, description?, props, subject, preview, component })`
467
497
  declares one. The Worker renders it with `@shware/workflow/react-email` (React's
468
498
  streaming renderer, which waits for react-email's `<Tailwind>`) and sends it
469
499
  through the host's email transport, from the template's own `from`:
470
500
 
471
501
  ```ts
472
- // src/email/welcome.tsx
502
+ // src/email/tip.tsx
473
503
  export default emailTemplate({
474
- id: 'welcome',
504
+ id: 'tip',
505
+ topic: 'tips',
475
506
  from: { email: 'noreply@acme.test', name: 'Acme' },
476
507
  replyTo: { email: 'support@acme.test', name: 'Acme Support' }, // left out: no Reply-To
477
- title: 'Welcome',
508
+ title: 'Weekly tip',
478
509
  props: strictObject({ name: string() }),
479
- subject: 'Welcome to Acme',
510
+ subject: 'One thing to try this week',
480
511
  preview: { name: 'John Doe' },
481
512
  component: ({ name }) => <Layout name={name}>…</Layout>,
482
513
  });
483
514
  ```
484
515
 
485
- There is no global sender: share addresses through a module of your own. The
486
- unsubscribe link is the template's `unsubscribeUrl`, else the config's
487
- `email.unsubscribeUrl`, else none (`resolveEmail` is the rule). A layout reads
488
- it from the render, never from a constant, so a template's own URL reaches
489
- its HTML:
516
+ Every template is one of two kinds, by type: a **topic** email names one of the
517
+ contract's `subscriptions.topics`, and a **transactional** email says
518
+ `transactional: true` (and takes no `unsubscribeUrl`). The kind decides what
519
+ the engine does before and after the send:
520
+
521
+ | Email | Before sending | Unsubscribe link, `List-Unsubscribe` |
522
+ | ------------- | -------------------------------------------------------------- | ------------------------------------- |
523
+ | topic | skipped when the user opted out of that topic, or of all email | yes |
524
+ | transactional | always sent (a receipt, a code, an invite) | none, whatever `email.unsubscribeUrl` |
525
+
526
+ There is no global sender: share addresses through a module of your own. A
527
+ topic email's unsubscribe link is the template's `unsubscribeUrl`, else the
528
+ config's `email.unsubscribeUrl`, else none; a transactional email never has one
529
+ (`resolveEmail` is the rule). A layout reads it from the render, never from a
530
+ constant, so a template's own URL reaches its HTML; the resolved `topic` is
531
+ there too, for a line like "you get these because you subscribed to tips":
490
532
 
491
533
  ```tsx
492
534
  import { useEmailContext } from '@shware/workflow/email-context';
@@ -527,10 +569,23 @@ An email with an unsubscribe link also carries `List-Unsubscribe` (RFC 2369), so
527
569
  a mail client's own unsubscribe button works. With reporting on (a Postgres store and
528
570
  `WORKFLOW_ORIGIN`), it names the copy's one-click endpoint `/t/u/<message>`, together with
529
571
  `List-Unsubscribe-Post: List-Unsubscribe=One-Click` (RFC 8058). Gmail and Yahoo require
530
- one-click unsubscribe for bulk senders. The provider's POST there unsubscribes at once, and the
531
- same URL opened in a browser asks first. Without reporting, the header names the template's own
532
- unsubscribe link, with no one-click claim. Only https URLs are named, so a local `http://`
533
- origin sends no header.
572
+ one-click unsubscribe for bulk senders. The provider's POST there unsubscribes at once from
573
+ the email's topic; the same URL opened in a browser (and the email's own link) asks first, with
574
+ two buttons: the email's topic, and all email. Without reporting, the header names the
575
+ template's own unsubscribe link, with no one-click claim. Only https URLs are named, so a local
576
+ `http://` origin sends no header.
577
+
578
+ What a user opted out of is the engine's record, per topic and channel: a topic email is
579
+ skipped while its topic (on email) or all email is opted out, a transactional email never is,
580
+ and `reachable('email')` reads the all-email opt-out only — a user unsubscribed from one topic
581
+ is still reachable, so an `exitWhen: not(reachable('email'))` fires on "all email", not on a
582
+ topic. An email opt-out says nothing about push: the same topic is opted out per channel. The
583
+ app reads and sets the record through `GET` / `PUT /subscriptions/:userId`
584
+ (`JourneyClient.getSubscriptions` / `setSubscriptions`), which is how a signed-in preference
585
+ page is built: the engine holds the truth, the page shows it. The all-email opt-out and the
586
+ topic opt-outs are separate records: `all: false` masks every topic, whatever its own flag says,
587
+ and `all: true` clears only the all-email opt-out — a topic opted out on its own stays off until
588
+ a patch names it.
534
589
 
535
590
  An email step refuses to send when the profile has no `email`.
536
591
  `GET /preview/<id>?props=<JSON>` renders a template, with the subject in the
@@ -538,13 +593,14 @@ An email step refuses to send when the profile has no `email`.
538
593
 
539
594
  ### Push
540
595
 
541
- `pushTemplate({ id, title, description?, props, preview, content })`, where
542
- `content(props)` returns `{ title, body, image?, url? }`: final text, never
596
+ `pushTemplate({ id, topic | transactional, title, description?, props, preview, content })`,
597
+ where `content(props)` returns `{ title, body, image?, url? }`: final text, never
543
598
  placeholder-expanded. `url` is the page a browser push opens.
544
599
 
545
600
  ```ts
546
601
  export default pushTemplate({
547
602
  id: 'onboarding_tip_push',
603
+ topic: 'tips',
548
604
  title: 'Onboarding tip (push)',
549
605
  props: strictObject({ name: string() }),
550
606
  preview: { name: 'John Doe' },
@@ -552,6 +608,18 @@ export default pushTemplate({
552
608
  });
553
609
  ```
554
610
 
611
+ A push is a **topic** push (one of the contract's `subscriptions.topics`) or a
612
+ **transactional** one (`transactional: true`: a code, a receipt, a reply), like
613
+ an email. A topic push is skipped while the user opted out of that topic on
614
+ push, or of all push; a transactional push always goes. The app records the
615
+ opt-outs through `PUT /subscriptions/:userId` (`JourneyClient.setSubscriptions`
616
+ with `{ push: { all?, topics? } }`), which is the in-app switch App Store Review
617
+ Guideline 4.5.4 requires for marketing pushes: `push.all: false` is "no
618
+ promotional notifications", a topic `false` is one category off. The opt-outs are
619
+ per channel: a topic switched off for push is still sent by email.
620
+ `reachable('push')` is a device plus no all-push opt-out; a topic opt-out leaves
621
+ it true. Changing `push.all` wakes the waits on it, as a device change does.
622
+
555
623
  Pushes go to the devices the engine keeps. The app registers each token with
556
624
  `JourneyClient.registerDevice(userId, { token, platform })`, and a token moves
557
625
  to the latest user that registers it. Each platform is turned on by the config,
@@ -636,20 +704,20 @@ Discord; supply anything else with `journeyWorker({ messages })`.
636
704
 
637
705
  `defineConfig` takes:
638
706
 
639
- | Field | Holds |
640
- | ----------- | ------------------------------------------------------------------------------ |
641
- | `title` | The Studio title |
642
- | `contract` | The `defineContract(...)` every `/events` and `/identify` is validated against |
643
- | `workflows` | The workflows to deploy |
644
- | `segments` | Named segments |
645
- | `actions` | Custom actions `.run()` uses |
646
- | `templates` | The registries: `{ email?, push?, discord?, slack? }` |
647
- | `email` | `{ unsubscribeUrl?, tracking? }`: what every email template shares |
648
- | `runtime` | Per mode (`development`, `production`, …): `{ timeScale?, logMessages? }` |
649
- | `apns` | `{ topic, keyId, teamId, environment? }` |
650
- | `fcm` | `{ androidChannelId? }` |
651
- | `webPush` | `{ subject, openedEvent? }` |
652
- | `database` | `{ schema? }`: the Postgres schema, `workflow` by default |
707
+ | Field | Holds |
708
+ | ----------- | ----------------------------------------------------------------------------------- |
709
+ | `title` | The Studio title |
710
+ | `contract` | The `defineContract(...)` every `/events` and `/identify` is validated against |
711
+ | `workflows` | The workflows to deploy |
712
+ | `segments` | Named segments |
713
+ | `actions` | Custom actions `.run()` uses |
714
+ | `templates` | The registries: `{ email?, push?, discord?, slack? }`; topics typed by the contract |
715
+ | `email` | `{ unsubscribeUrl?, tracking? }`: what every topic email template shares |
716
+ | `runtime` | Per mode (`development`, `production`, …): `{ timeScale?, logMessages? }` |
717
+ | `apns` | `{ topic, keyId, teamId, environment? }` |
718
+ | `fcm` | `{ androidChannelId? }` |
719
+ | `webPush` | `{ subject, openedEvent? }` |
720
+ | `database` | `{ schema? }`: the Postgres schema, `workflow` by default |
653
721
 
654
722
  The `ENVIRONMENT` var picks the `runtime` entry (production when unset).
655
723
  `timeScale` fast-forwards every duration: 600 turns "1 day" into 2.4 minutes.
@@ -689,12 +757,39 @@ const journeys = new JourneyClient({ contract, origin, token });
689
757
  | `unbindDevice(token)` | `POST /devices/unbind` | Signed out: the token stays, bound to nobody |
690
758
  | `removeDevice(token)` | `POST /devices/remove` | Forget a token for good |
691
759
  | `messageOpened(userId, messageId)` | `POST /messages/opened` | A journey push tapped open (the `message_id` it carried) |
760
+ | `getSubscriptions(userId)` | `GET /subscriptions/…` | `{ email, push }`, each `{ all, topics }`, `true` = on |
761
+ | `setSubscriptions(userId, patch)` | `PUT /subscriptions/…` | Change what the patch names; answers the new state |
692
762
  | `forgetUser(userId)` | `POST /users/forget` | Stop the user's journeys and erase their data |
693
763
  | `deploy(bundle)` | `POST /deploy` | Deploy a compiled bundle |
694
764
 
695
765
  Pass an `id` to `track` whenever a caller may retry; see
696
766
  [Give each event an `id`](#give-each-event-an-id).
697
767
 
768
+ `getSubscriptions` and `setSubscriptions` are typed by the contract's
769
+ `subscriptions.topics`, and a topic it does not declare is refused before the
770
+ request. The record is topic × channel: `email` and `push` each list every
771
+ topic. A preference page is a thin proxy over them:
772
+
773
+ ```ts
774
+ const { email, push } = await journeys.getSubscriptions(userId);
775
+ // email: { all: false, topics: { promotions: false, newsletter: true, tips: true } }
776
+ // push: { all: true, topics: { promotions: true, newsletter: true, tips: true } }
777
+ // `all: false` masks every topic: newsletter reads true, but no email is sent until `all` is
778
+ // true again. Each flag is its own record, so a preference page shows `all` as the master
779
+ // switch and the topics as they are. Push is untouched by the email record.
780
+ await journeys.setSubscriptions(userId, { email: { all: true } });
781
+ // email: { all: true, topics: { promotions: false, newsletter: true, tips: true } }
782
+ // `all: true` cleared only the all-email opt-out; promotions stays off until named:
783
+ await journeys.setSubscriptions(userId, { email: { topics: { promotions: true } } });
784
+ await journeys.setSubscriptions(userId, { email: { all: false } }); // unsubscribe from everything
785
+ await journeys.setSubscriptions(userId, { push: { all: false } }); // the in-app "no promotional pushes"
786
+ await journeys.setSubscriptions(userId, { push: { topics: { promotions: false } } }); // one category off, on push only
787
+ ```
788
+
789
+ A "subscribe to all" button sends `all: true` plus every topic `true`; an
790
+ "unsubscribe from all" sends `all: false` and leaves the topics as they are, so
791
+ turning `all` back on restores the user's own choices.
792
+
698
793
  ## Compiling and planning
699
794
 
700
795
  `compileConfig(config)` returns the `BundleIR` the Worker deploys. It is
@@ -1016,14 +1111,25 @@ says `database: { schema }`, so their short names never meet the app's. The
1016
1111
  host owns the migrations. `npx workflow-ui generate --out <file>` (from
1017
1112
  `@shware/workflow-ui`) writes the tables as one drizzle file on that schema;
1018
1113
  re-export it from your drizzle schema and let drizzle-kit write the migration.
1019
- Run `--check` in CI to catch an SDK upgrade that changed them. The unique index
1114
+ Run `--check` in CI to catch an SDK upgrade that changed them. The file is laid
1115
+ out the way a prettier-compatible formatter at 100 columns lays it out, so
1116
+ formatting it changes nothing and a regeneration shows only real changes. The unique index
1020
1117
  on `event` is on `(user_id, event_id)`: regenerate and migrate before deploying —
1021
- the deploy check verifies the unique indexes as well as the columns, and refuses
1118
+ the deploy check verifies the unique indexes and constraints as well as the columns, and refuses
1022
1119
  to run until they match. Without drizzle,
1023
1120
  `renderPostgresDdl()` returns the same tables as plain DDL. Nothing creates or
1024
1121
  alters them at runtime: `POST /bundle/deploy` checks the live database first
1025
1122
  and answers 503 with every missing table or column.
1026
1123
 
1124
+ **Upgrading to 6.0 (topics).** `suppression` gains a nullable `topic`
1125
+ column, loses its `(user_id, channel)` primary key and gets a
1126
+ `UNIQUE NULLS NOT DISTINCT (user_id, channel, topic)` constraint (Postgres 15+),
1127
+ and `message` gains a nullable `topic` (written for email and push copies).
1128
+ Regenerate the drizzle file and let drizzle-kit write the migration; it needs no
1129
+ data step. Rows from before keep their meaning: a `suppression` row whose
1130
+ `topic` is null is an opt-out from the whole channel, which is what every
1131
+ unsubscribe recorded before topics was.
1132
+
1027
1133
  ### Deploying is `wrangler deploy`
1028
1134
 
1029
1135
  The journeys are compiled into the Worker, so a new version carries its own
@@ -1088,14 +1194,31 @@ On Postgres the engine also keeps:
1088
1194
  - `POST /devices` takes `{ userId, token, platform, ts? }`;
1089
1195
  `POST /devices/unbind` and `POST /devices/remove` take `{ token }`.
1090
1196
  - `POST /messages/opened` takes `{ userId, messageId }`.
1091
- - `POST /users/forget` takes `{ userId }`.
1197
+ - `GET /subscriptions/:userId` answers `{ email: { all, topics }, push: { all, topics } }`
1198
+ (`true` is subscribed; each channel's `topics` has one key per topic the
1199
+ deployed bundle declares). `PUT /subscriptions/:userId` takes a partial body
1200
+ `{ email?: { all?, topics? }, push?: { all?, topics? } }` and changes only
1201
+ what it names, per channel: `all: false` opts out of the whole channel,
1202
+ `topics: { newsletter: false }` of one topic on it, and `all: true` clears
1203
+ the channel-wide opt-out only (a topic opted out on its own stays off until
1204
+ named). An answer's `all: false` masks every topic of that channel, whatever
1205
+ the topic's own flag says. An undeclared topic, an unknown channel or a
1206
+ non-boolean answers 400 with the field paths; an erased user 410. Changing
1207
+ `email.all` wakes the waits on `reachable('email')`, `push.all` those on
1208
+ `reachable('push')`.
1209
+ - `POST /users/forget` takes `{ userId }`; the erasure takes the user's opt-outs
1210
+ with the rest, since nothing is ever sent to that id again.
1092
1211
  - `POST /deploy` takes a compiled bundle and swaps the routing table atomically.
1093
1212
 
1094
1213
  `journeyWorker` adds `GET /bundle` (the compiled config), `POST /bundle/deploy`
1095
1214
  (deploy it), `GET /preview/<key>`, `POST /segments/sweep`, and the `/t/...`
1096
- tracking routes recipients open, which need no bearer. With a contract, an
1097
- event or identify it refuses is answered with a 400 and the field paths, before
1098
- anything is stored, woken or started.
1215
+ tracking routes recipients open, which need no bearer. `POST /t/u/<message>`
1216
+ (the one-click unsubscribe, and the confirmation page's first button) opts the
1217
+ recipient out of that email's topic; with `?scope=all` (the second button) out
1218
+ of every email. A transactional email never carried the link, so every `/t/u`
1219
+ variant answers 404 for it. With a contract, an event or identify it refuses is
1220
+ answered with a 400 and the field paths, before anything is stored, woken or
1221
+ started.
1099
1222
 
1100
1223
  ### Give each event an `id`
1101
1224
 
@@ -1,4 +1,4 @@
1
- //#region \0rolldown/runtime.js
1
+ // \0rolldown/runtime.js
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -19,5 +19,4 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
19
19
  value: mod,
20
20
  enumerable: true
21
21
  }) : target, mod));
22
- //#endregion
23
22
  exports.__toESM = __toESM;
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_http2_client = require("./http2-client.cjs");
3
3
  let node_http = require("node:http");
4
- //#region src/apns-relay.ts
4
+ // src/apns-relay.ts
5
5
  const DEFAULT_ALLOW = ["https://api.push.apple.com", "https://api.sandbox.push.apple.com"];
6
6
  /** Request headers APNs reads; everything else (host, content-length, …) is the relay's own business. */
7
7
  const FORWARDED = [
@@ -86,7 +86,6 @@ function startApnsRelay(options) {
86
86
  });
87
87
  });
88
88
  }
89
- //#endregion
90
89
  exports.startApnsRelay = startApnsRelay;
91
90
 
92
91
  //# sourceMappingURL=apns-relay.cjs.map
@@ -1,4 +1,3 @@
1
- //#region src/apns-relay.d.ts
2
1
  /**
3
2
  * `@shware/workflow/apns-relay` — a development-only HTTP/1.1 → HTTP/2 relay
4
3
  * for APNs, run under Node next to `wrangler dev`.
@@ -24,5 +23,4 @@ export interface ApnsRelay {
24
23
  close(): Promise<void>;
25
24
  }
26
25
  export declare function startApnsRelay(options: ApnsRelayOptions): Promise<ApnsRelay>;
27
- //#endregion
28
26
  //# sourceMappingURL=apns-relay.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apns-relay.d.cts","names":[],"sources":["../src/apns-relay.ts"],"mappings":";;;;;;;;;;;;;;iBAiBiB;EACf;;EAEA;;EAEA;;iBAGe;EACf;EACA,SAAS;;wBAiBK,eAAe,SAAS,mBAAmB,QAAQ"}
1
+ {"version":3,"file":"apns-relay.d.cts","names":[],"sources":["../src/apns-relay.ts"],"mappings":";;;;;;;;;;;;;iBAiBiB;EACf;;EAEA;;EAEA;;iBAGe;EACf;EACA,SAAS;;wBAiBK,eAAe,SAAS,mBAAmB,QAAQ"}
@@ -1,4 +1,3 @@
1
- //#region src/apns-relay.d.ts
2
1
  /**
3
2
  * `@shware/workflow/apns-relay` — a development-only HTTP/1.1 → HTTP/2 relay
4
3
  * for APNs, run under Node next to `wrangler dev`.
@@ -24,5 +23,4 @@ export interface ApnsRelay {
24
23
  close(): Promise<void>;
25
24
  }
26
25
  export declare function startApnsRelay(options: ApnsRelayOptions): Promise<ApnsRelay>;
27
- //#endregion
28
26
  //# sourceMappingURL=apns-relay.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apns-relay.d.mts","names":[],"sources":["../src/apns-relay.ts"],"mappings":";;;;;;;;;;;;;;iBAiBiB;EACf;;EAEA;;EAEA;;iBAGe;EACf;EACA,SAAS;;wBAiBK,eAAe,SAAS,mBAAmB,QAAQ"}
1
+ {"version":3,"file":"apns-relay.d.mts","names":[],"sources":["../src/apns-relay.ts"],"mappings":";;;;;;;;;;;;;iBAiBiB;EACf;;EAEA;;EAEA;;iBAGe;EACf;EACA,SAAS;;wBAiBK,eAAe,SAAS,mBAAmB,QAAQ"}
@@ -1,6 +1,6 @@
1
1
  import { http2Sessions } from "./http2-client.mjs";
2
2
  import { createServer } from "node:http";
3
- //#region src/apns-relay.ts
3
+ // src/apns-relay.ts
4
4
  const DEFAULT_ALLOW = ["https://api.push.apple.com", "https://api.sandbox.push.apple.com"];
5
5
  /** Request headers APNs reads; everything else (host, content-length, …) is the relay's own business. */
6
6
  const FORWARDED = [
@@ -85,7 +85,6 @@ function startApnsRelay(options) {
85
85
  });
86
86
  });
87
87
  }
88
- //#endregion
89
88
  export { startApnsRelay };
90
89
 
91
90
  //# sourceMappingURL=apns-relay.mjs.map
package/dist/apns.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_engine_retry = require("./engine/retry.cjs");
3
3
  const require_jwt = require("./jwt.cjs");
4
4
  let node_buffer = require("node:buffer");
5
- //#region src/apns.ts
5
+ // src/apns.ts
6
6
  const APNS_HOSTS = {
7
7
  sandbox: "https://api.sandbox.push.apple.com",
8
8
  production: "https://api.push.apple.com"
@@ -196,7 +196,6 @@ function apnsKeyFromBase64(value) {
196
196
  if (!pem.includes("-----BEGIN PRIVATE KEY-----")) throw new require_engine_retry.PermanentError("APNs key is not a PKCS #8 PEM (.p8) file");
197
197
  return pem;
198
198
  }
199
- //#endregion
200
199
  exports.APNS_HOSTS = APNS_HOSTS;
201
200
  exports.ApnsProviderToken = ApnsProviderToken;
202
201
  exports.ApnsPushSender = ApnsPushSender;
package/dist/apns.d.cts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { MessageSender, OutboundMessage, SendResult } from "./engine/ports.cjs";
2
2
  import "./engine/index.cjs";
3
3
  import { PushRenderer } from "./push.cjs";
4
- //#region src/apns.d.ts
5
4
  /**
6
5
  * `@shware/workflow/apns` — iOS push delivery straight to the Apple Push
7
6
  * Notification service, token-based (an APNs auth key, the `.p8` file from the
@@ -105,5 +104,4 @@ export declare function apnsReason(body: string): string;
105
104
  export declare function signApnsJwt(key: ApnsProviderTokenOptions, nowMs?: number): Promise<string>;
106
105
  /** The `.p8` as it is usually shipped in a secret: base64 of the file. */
107
106
  export declare function apnsKeyFromBase64(value: string): string;
108
- //#endregion
109
107
  //# sourceMappingURL=apns.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apns.d.cts","names":[],"sources":["../src/apns.ts"],"mappings":";;;;;;;;;;;;;;;;;iBAoBiB;;EAEf;;EAEA;;EAEA;;iBAGe;;EAEf,aAAa;;EAEb;;;;;;;EAOA;EACA,QAAQ;;;;;;EAMR;;EAEA,eAAe;;qBAGJ;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBAsBW,oBAAoB;;;;;;;;wBAsBX,cAAc,yBAAyB;;;;;;;;qBAqBhD;mBAIkB;UAHrB;UACA;EAER,YAA6B,SAAS;;EAGhC,MAAM,eAAmB;;EAgB/B;;qBAKW,0BAA0B;mBACR;EAA7B,YAA6B,SAAS;EAEhC,KAAK,SAAS,kBAAkB,eAAe;;;wBAkFvC,WAAW;;wBAUL,YACpB,KAAK,0BACL,iBACC;;wBAoBa,kBAAkB"}
1
+ {"version":3,"file":"apns.d.cts","names":[],"sources":["../src/apns.ts"],"mappings":";;;;;;;;;;;;;;;;iBAoBiB;;EAEf;;EAEA;;EAEA;;iBAGe;;EAEf,aAAa;;EAEb;;;;;;;EAOA;EACA,QAAQ;;;;;;EAMR;;EAEA,eAAe;;qBAGJ;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBAsBW,oBAAoB;;;;;;;;wBAsBX,cAAc,yBAAyB;;;;;;;;qBAqBhD;mBAIkB;UAHrB;UACA;EAER,YAA6B,SAAS;;EAGhC,MAAM,eAAmB;;EAgB/B;;qBAKW,0BAA0B;mBACR;EAA7B,YAA6B,SAAS;EAEhC,KAAK,SAAS,kBAAkB,eAAe;;;wBAkFvC,WAAW;;wBAUL,YACpB,KAAK,0BACL,iBACC;;wBAoBa,kBAAkB"}
package/dist/apns.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { MessageSender, OutboundMessage, SendResult } from "./engine/ports.mjs";
2
2
  import "./engine/index.mjs";
3
3
  import { PushRenderer } from "./push.mjs";
4
- //#region src/apns.d.ts
5
4
  /**
6
5
  * `@shware/workflow/apns` — iOS push delivery straight to the Apple Push
7
6
  * Notification service, token-based (an APNs auth key, the `.p8` file from the
@@ -105,5 +104,4 @@ export declare function apnsReason(body: string): string;
105
104
  export declare function signApnsJwt(key: ApnsProviderTokenOptions, nowMs?: number): Promise<string>;
106
105
  /** The `.p8` as it is usually shipped in a secret: base64 of the file. */
107
106
  export declare function apnsKeyFromBase64(value: string): string;
108
- //#endregion
109
107
  //# sourceMappingURL=apns.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apns.d.mts","names":[],"sources":["../src/apns.ts"],"mappings":";;;;;;;;;;;;;;;;;iBAoBiB;;EAEf;;EAEA;;EAEA;;iBAGe;;EAEf,aAAa;;EAEb;;;;;;;EAOA;EACA,QAAQ;;;;;;EAMR;;EAEA,eAAe;;qBAGJ;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBAsBW,oBAAoB;;;;;;;;wBAsBX,cAAc,yBAAyB;;;;;;;;qBAqBhD;mBAIkB;UAHrB;UACA;EAER,YAA6B,SAAS;;EAGhC,MAAM,eAAmB;;EAgB/B;;qBAKW,0BAA0B;mBACR;EAA7B,YAA6B,SAAS;EAEhC,KAAK,SAAS,kBAAkB,eAAe;;;wBAkFvC,WAAW;;wBAUL,YACpB,KAAK,0BACL,iBACC;;wBAoBa,kBAAkB"}
1
+ {"version":3,"file":"apns.d.mts","names":[],"sources":["../src/apns.ts"],"mappings":";;;;;;;;;;;;;;;;iBAoBiB;;EAEf;;EAEA;;EAEA;;iBAGe;;EAEf,aAAa;;EAEb;;;;;;;EAOA;EACA,QAAQ;;;;;;EAMR;;EAEA,eAAe;;qBAGJ;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBAsBW,oBAAoB;;;;;;;;wBAsBX,cAAc,yBAAyB;;;;;;;;qBAqBhD;mBAIkB;UAHrB;UACA;EAER,YAA6B,SAAS;;EAGhC,MAAM,eAAmB;;EAgB/B;;qBAKW,0BAA0B;mBACR;EAA7B,YAA6B,SAAS;EAEhC,KAAK,SAAS,kBAAkB,eAAe;;;wBAkFvC,WAAW;;wBAUL,YACpB,KAAK,0BACL,iBACC;;wBAoBa,kBAAkB"}
package/dist/apns.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { PermanentError, isRetryableStatus } from "./engine/retry.mjs";
2
2
  import { base64url, pemToDer } from "./jwt.mjs";
3
3
  import { Buffer } from "node:buffer";
4
- //#region src/apns.ts
4
+ // src/apns.ts
5
5
  const APNS_HOSTS = {
6
6
  sandbox: "https://api.sandbox.push.apple.com",
7
7
  production: "https://api.push.apple.com"
@@ -195,7 +195,6 @@ function apnsKeyFromBase64(value) {
195
195
  if (!pem.includes("-----BEGIN PRIVATE KEY-----")) throw new PermanentError("APNs key is not a PKCS #8 PEM (.p8) file");
196
196
  return pem;
197
197
  }
198
- //#endregion
199
198
  export { APNS_HOSTS, ApnsProviderToken, ApnsPushSender, DEAD_TOKEN_REASONS, apnsIdFromKey, apnsKeyFromBase64, apnsReason, signApnsJwt };
200
199
 
201
200
  //# sourceMappingURL=apns.mjs.map
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_engine_retry = require("../engine/retry.cjs");
3
3
  let _aws_durable_execution_sdk_js = require("@aws/durable-execution-sdk-js");
4
- //#region src/aws/engine-step.ts
4
+ // src/aws/engine-step.ts
5
5
  /**
6
6
  * EngineStep over a Lambda durable execution.
7
7
  *
@@ -96,7 +96,6 @@ var AwsEngineStep = class {
96
96
  }
97
97
  }
98
98
  };
99
- //#endregion
100
99
  exports.AwsEngineStep = AwsEngineStep;
101
100
  exports.stepRetry = stepRetry;
102
101
 
@@ -2,7 +2,6 @@ import { EngineStep } from "../engine/ports.cjs";
2
2
  import { ExecutionRegistry, JourneyStore } from "../store/index.cjs";
3
3
  import { LambdaApi } from "./lambda-api.cjs";
4
4
  import { DurableContext, RetryDecision } from "@aws/durable-execution-sdk-js";
5
- //#region src/aws/engine-step.d.ts
6
5
  /**
7
6
  * EngineStep over a Lambda durable execution.
8
7
  *
@@ -40,5 +39,4 @@ export declare class AwsEngineStep implements EngineStep {
40
39
  deadlineMs: number;
41
40
  }): Promise<'event' | 'timeout'>;
42
41
  }
43
- //#endregion
44
42
  //# sourceMappingURL=engine-step.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine-step.d.cts","names":[],"sources":["../../src/aws/engine-step.ts"],"mappings":";;;;;;;;;;;;;;;;wBAuBgB,UAAU,OAAO,OAAO,kBAAkB;qBAa7C,yBAAyB;mBAKjB;mBACA;mBACA;mBACA;mBACA;mBACA;UATX;UACA;EAER,YACmB,SAAS,gBACT,OAAO,cACP,YAAY,mBACZ,QAAQ,WACR,gBACA;EAGnB,GAAG,GAAG,cAAc,UAAU,QAAQ,KAAK,QAAQ;EAI7C,MAAM,cAAc,aAAa;EAMjC,UACJ,cACA,2BACA;IAAW;MACV;EAoCG,YAAY,eAAe;;;;;EAsB3B,YACJ,cACA;IAAS;IAAmB;MAC3B"}
1
+ {"version":3,"file":"engine-step.d.cts","names":[],"sources":["../../src/aws/engine-step.ts"],"mappings":";;;;;;;;;;;;;;;wBAuBgB,UAAU,OAAO,OAAO,kBAAkB;qBAa7C,yBAAyB;mBAKjB;mBACA;mBACA;mBACA;mBACA;mBACA;UATX;UACA;EAER,YACmB,SAAS,gBACT,OAAO,cACP,YAAY,mBACZ,QAAQ,WACR,gBACA;EAGnB,GAAG,GAAG,cAAc,UAAU,QAAQ,KAAK,QAAQ;EAI7C,MAAM,cAAc,aAAa;EAMjC,UACJ,cACA,2BACA;IAAW;MACV;EAoCG,YAAY,eAAe;;;;;EAsB3B,YACJ,cACA;IAAS;IAAmB;MAC3B"}
@@ -2,7 +2,6 @@ import { EngineStep } from "../engine/ports.mjs";
2
2
  import { ExecutionRegistry, JourneyStore } from "../store/index.mjs";
3
3
  import { LambdaApi } from "./lambda-api.mjs";
4
4
  import { DurableContext, RetryDecision } from "@aws/durable-execution-sdk-js";
5
- //#region src/aws/engine-step.d.ts
6
5
  /**
7
6
  * EngineStep over a Lambda durable execution.
8
7
  *
@@ -40,5 +39,4 @@ export declare class AwsEngineStep implements EngineStep {
40
39
  deadlineMs: number;
41
40
  }): Promise<'event' | 'timeout'>;
42
41
  }
43
- //#endregion
44
42
  //# sourceMappingURL=engine-step.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine-step.d.mts","names":[],"sources":["../../src/aws/engine-step.ts"],"mappings":";;;;;;;;;;;;;;;;wBAuBgB,UAAU,OAAO,OAAO,kBAAkB;qBAa7C,yBAAyB;mBAKjB;mBACA;mBACA;mBACA;mBACA;mBACA;UATX;UACA;EAER,YACmB,SAAS,gBACT,OAAO,cACP,YAAY,mBACZ,QAAQ,WACR,gBACA;EAGnB,GAAG,GAAG,cAAc,UAAU,QAAQ,KAAK,QAAQ;EAI7C,MAAM,cAAc,aAAa;EAMjC,UACJ,cACA,2BACA;IAAW;MACV;EAoCG,YAAY,eAAe;;;;;EAsB3B,YACJ,cACA;IAAS;IAAmB;MAC3B"}
1
+ {"version":3,"file":"engine-step.d.mts","names":[],"sources":["../../src/aws/engine-step.ts"],"mappings":";;;;;;;;;;;;;;;wBAuBgB,UAAU,OAAO,OAAO,kBAAkB;qBAa7C,yBAAyB;mBAKjB;mBACA;mBACA;mBACA;mBACA;mBACA;UATX;UACA;EAER,YACmB,SAAS,gBACT,OAAO,cACP,YAAY,mBACZ,QAAQ,WACR,gBACA;EAGnB,GAAG,GAAG,cAAc,UAAU,QAAQ,KAAK,QAAQ;EAI7C,MAAM,cAAc,aAAa;EAMjC,UACJ,cACA,2BACA;IAAW;MACV;EAoCG,YAAY,eAAe;;;;;EAsB3B,YACJ,cACA;IAAS;IAAmB;MAC3B"}
@@ -1,6 +1,6 @@
1
1
  import { isRetryable } from "../engine/retry.mjs";
2
2
  import { CallbackTimeoutError } from "@aws/durable-execution-sdk-js";
3
- //#region src/aws/engine-step.ts
3
+ // src/aws/engine-step.ts
4
4
  /**
5
5
  * EngineStep over a Lambda durable execution.
6
6
  *
@@ -95,7 +95,6 @@ var AwsEngineStep = class {
95
95
  }
96
96
  }
97
97
  };
98
- //#endregion
99
98
  export { AwsEngineStep, stepRetry };
100
99
 
101
100
  //# sourceMappingURL=engine-step.mjs.map
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let node_buffer = require("node:buffer");
3
- //#region src/aws/function-url.ts
3
+ // src/aws/function-url.ts
4
4
  /**
5
5
  * An HTTP request, told apart by the event's own top-level shape — the Function URL wraps
6
6
  * every request in `requestContext.http`, so no request body can pass for anything else.
@@ -46,7 +46,6 @@ async function fromResponse(response, method) {
46
46
  isBase64Encoded: !textual
47
47
  };
48
48
  }
49
- //#endregion
50
49
  exports.fromResponse = fromResponse;
51
50
  exports.isFunctionUrlEvent = isFunctionUrlEvent;
52
51
  exports.toRequest = toRequest;
@@ -1,4 +1,3 @@
1
- //#region src/aws/function-url.d.ts
2
1
  /**
3
2
  * Lambda Function URL events (payload format 2.0) as fetch `Request`s, and `Response`s back as
4
3
  * the result Lambda turns into the HTTP response — so the host's HTTP API runs unchanged.
@@ -34,5 +33,4 @@ export interface FunctionUrlResult {
34
33
  export declare function isFunctionUrlEvent(event: unknown): event is FunctionUrlEvent;
35
34
  export declare function toRequest(event: FunctionUrlEvent): Request;
36
35
  export declare function fromResponse(response: Response, method: string): Promise<FunctionUrlResult>;
37
- //#endregion
38
36
  //# sourceMappingURL=function-url.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"function-url.d.cts","names":[],"sources":["../../src/aws/function-url.ts"],"mappings":";;;;;iBAMiB;EACf;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA;IACE;IACA;MAAQ;MAAgB;MAAmB;;;;iBAI9B;EACf;EACA,SAAS;EACT;EACA;EACA;;;;;;wBAOc,mBAAmB,iBAAiB,SAAS;wBAoB7C,UAAU,OAAO,mBAAmB;wBA4B9B,aAAa,UAAU,UAAU,iBAAiB,QAAQ"}
1
+ {"version":3,"file":"function-url.d.cts","names":[],"sources":["../../src/aws/function-url.ts"],"mappings":";;;;iBAMiB;EACf;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA;IACE;IACA;MAAQ;MAAgB;MAAmB;;;;iBAI9B;EACf;EACA,SAAS;EACT;EACA;EACA;;;;;;wBAOc,mBAAmB,iBAAiB,SAAS;wBAoB7C,UAAU,OAAO,mBAAmB;wBA4B9B,aAAa,UAAU,UAAU,iBAAiB,QAAQ"}
@@ -1,4 +1,3 @@
1
- //#region src/aws/function-url.d.ts
2
1
  /**
3
2
  * Lambda Function URL events (payload format 2.0) as fetch `Request`s, and `Response`s back as
4
3
  * the result Lambda turns into the HTTP response — so the host's HTTP API runs unchanged.
@@ -34,5 +33,4 @@ export interface FunctionUrlResult {
34
33
  export declare function isFunctionUrlEvent(event: unknown): event is FunctionUrlEvent;
35
34
  export declare function toRequest(event: FunctionUrlEvent): Request;
36
35
  export declare function fromResponse(response: Response, method: string): Promise<FunctionUrlResult>;
37
- //#endregion
38
36
  //# sourceMappingURL=function-url.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"function-url.d.mts","names":[],"sources":["../../src/aws/function-url.ts"],"mappings":";;;;;iBAMiB;EACf;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA;IACE;IACA;MAAQ;MAAgB;MAAmB;;;;iBAI9B;EACf;EACA,SAAS;EACT;EACA;EACA;;;;;;wBAOc,mBAAmB,iBAAiB,SAAS;wBAoB7C,UAAU,OAAO,mBAAmB;wBA4B9B,aAAa,UAAU,UAAU,iBAAiB,QAAQ"}
1
+ {"version":3,"file":"function-url.d.mts","names":[],"sources":["../../src/aws/function-url.ts"],"mappings":";;;;iBAMiB;EACf;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA;IACE;IACA;MAAQ;MAAgB;MAAmB;;;;iBAI9B;EACf;EACA,SAAS;EACT;EACA;EACA;;;;;;wBAOc,mBAAmB,iBAAiB,SAAS;wBAoB7C,UAAU,OAAO,mBAAmB;wBA4B9B,aAAa,UAAU,UAAU,iBAAiB,QAAQ"}