@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/dist/ir.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.cjs","names":["z"],"sources":["../src/ir.ts"],"sourcesContent":["import * as z from 'zod/mini';\n\n/**\n * IR (Intermediate Representation) — what the DSL compiles to: serializable\n * JSON. It is the three-way contract between the engine that interprets it,\n * the UI (react-flow) that renders it, and diff / audit tooling.\n *\n * Validation strategy: the zod/mini schemas are the authoritative definition.\n * TS types are either inferred from a schema or hand-written under the same\n * name (zod cannot infer recursive types; the hand-written type is anchored\n * with a ZodMiniType<T> annotation, so any drift fails to compile). IR crosses\n * process boundaries (database, network, UI), so runtime validation is a must.\n *\n * ## Versioning (two independent axes)\n *\n * 1. IR format version (irVersion): evolution of the IR schema itself. Adding\n * optional fields does not bump it; only structurally incompatible changes\n * do (changing a discriminant, dropping a field, altering semantics).\n * Readers dispatch on irVersion to the matching schema/migrator; writers\n * always write the current version.\n * 2. Content version (contentHash): a content-addressed id for a single\n * definition's **execution semantics** — the canonical-JSON hash after\n * metadata (meta / label / reason) is stripped, see hash.ts. It is used to:\n * - pin a version when a user enters, so an in-flight journey runs the\n * pinned version to completion (the default policy; compatible hot\n * updates are a future explicit-migration topic). Known exception:\n * segment conditions are resolved **by id at evaluation time** — a\n * segment redeploy changes behaviour of in-flight journeys that\n * reference it. Pinning covers the workflow's own structure; per-hash\n * segment snapshots are future work;\n * - diff on deploy: same hash means unchanged, skip publishing;\n * - audit: answer \"which version was this user on\" at any point.\n *\n * ## Node ids\n *\n * Derived from the structural path at compile time — stable and deterministic:\n * root level '0', '1', …; the j-th child of a branch's i-th case is\n * '{branchId}.c{i}.{j}', the default arm '{branchId}.o.{j}'; cohort arms use\n * the arm name '{cohortId}.{armName}.{j}'; a waitUntil timeout flow '{id}.t.{j}'.\n * Editing a node's parameters keeps its id; inserting a node shifts the ids of\n * its later siblings (a known trade-off — locating in-flight users relies on\n * the pinned version rather than cross-version id alignment, and cross-version\n * mapping is an explicit migrator's job).\n */\n\nexport const IR_VERSION = 2;\n\n/* -------------------------------- Base values ------------------------------- */\n\nexport const ScalarIR = z.union([z.string(), z.number(), z.boolean()]);\nexport type ScalarIR = z.infer<typeof ScalarIR>;\n\n/** Duration: `value` keeps the DSL literal ('23 hours', for display), `ms` is what the engine uses. */\n/*\n * TODO: `value` is hashed alongside `ms`, so '7 days' / '1 week' / '168 hours'\n * — identical to the engine, which only reads ms — produce three different\n * contentHashes. Rewording a duration therefore reports as a semantic change in\n * plan and repins in-flight users. Moving `value` out of the hash (it is a\n * display string) would fix it; deferred because it changes existing hashes.\n */\nexport const DurationIR = z.object({ value: z.string(), ms: z.number() });\nexport type DurationIR = z.infer<typeof DurationIR>;\n\n/** User-property reference — isomorphic to the DSL's UserPropertyRef once serialized (phantom type dropped). */\nexport const UserPropertyRefIR = z.object({\n type: z.literal('user_property'),\n path: z.string(),\n});\nexport type UserPropertyRefIR = z.infer<typeof UserPropertyRefIR>;\n\n/** A message prop / event payload value: either a literal or a user-property reference. */\nexport const PropValueIR = z.union([ScalarIR, UserPropertyRefIR]);\nexport type PropValueIR = z.infer<typeof PropValueIR>;\n\nexport const ChannelIR = z.enum(['email', 'sms', 'push', 'in_app', 'slack', 'discord', 'survey']);\nexport type ChannelIR = z.infer<typeof ChannelIR>;\n\nexport const WeekdayIR = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);\nexport type WeekdayIR = z.infer<typeof WeekdayIR>;\n\n/* --------------------------------- Provenance -------------------------------- */\n\n/**\n * Source location of the builder call that produced a definition — the IR's\n * source map. Lives under `meta`, so it is **excluded from contentHash**\n * (see hash.ts): provenance never affects execution identity or plan.\n * `file` is cwd-relative when compiled under Node, a URL under Vite dev.\n */\nexport const SourceLocIR = z.object({\n file: z.string(),\n line: z.number(),\n column: z.number(),\n});\nexport type SourceLocIR = z.infer<typeof SourceLocIR>;\n\n/** Node-level metadata: provenance only, for now. Excluded from contentHash. */\nexport const NodeMetaIR = z.object({\n loc: z.optional(SourceLocIR),\n});\nexport type NodeMetaIR = z.infer<typeof NodeMetaIR>;\n\n/* -------------------------------- Conditions -------------------------------- */\n\nexport const PropertyOperatorIR = z.enum([\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'between',\n 'not_between',\n 'in_array',\n 'not_in_array',\n 'exists',\n 'not_exists',\n 'contains',\n 'not_contains',\n]);\nexport type PropertyOperatorIR = z.infer<typeof PropertyOperatorIR>;\n\n/**\n * Condition expression tree. The shape of value/values follows `op`:\n * eq/ne/gt/gte/lt/lte/contains/not_contains → value; in_array/not_in_array →\n * values; between/not_between → values = [min, max]; exists/not_exists → neither.\n *\n * `payload` predicates test the payload of an event (dotted paths reach nested\n * fields). They are only valid inside a `where` subtree — `performed.where`\n * and the event trigger's `where` — where an event row is in scope; the\n * compiler (compileBundle) and the evaluator both enforce the placement.\n * TODO: runtime refinement narrowing by op.\n */\n/**\n * Provenance rides on conditions too, so the studio can point at the exact\n * `eq(...)` / `and(...)` that produced a node — same rule as nodes: `meta` is\n * dropped before hashing, so carrying it never affects execution identity.\n */\ninterface ConditionBaseIR {\n meta?: NodeMetaIR | undefined;\n}\n\nexport type ConditionIR =\n | (ConditionBaseIR & { type: 'and'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'or'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'not'; condition: ConditionIR })\n /** Reference a segment by id (defined in SegmentIR, versioned separately). */\n | (ConditionBaseIR & { type: 'segment'; segment: string })\n | (ConditionBaseIR & {\n type: 'property';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n /** Event payload predicate; `path` is dotted for nested fields ('tags.utm_source'). */\n type: 'payload';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n type: 'performed';\n event: string;\n /** Payload filter: only events matching it count (a payload-only subtree). */\n where?: ConditionIR | undefined;\n within?: DurationIR | undefined;\n count?: number | undefined;\n })\n /**\n * The user can be reached on the channel right now: for push, the host's\n * device directory lists at least one device; for the others, the channel's\n * recipient property (email, phone, …) is set.\n */\n | (ConditionBaseIR & { type: 'reachable'; channel: ChannelIR });\n\nconst conditionBase = { meta: z.optional(NodeMetaIR) };\n\nexport const ConditionIR: z.ZodMiniType<ConditionIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({ ...conditionBase, type: z.literal('and'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('or'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('not'), condition: ConditionIR }),\n z.object({ ...conditionBase, type: z.literal('segment'), segment: z.string() }),\n z.object({\n ...conditionBase,\n type: z.literal('property'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('payload'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('performed'),\n event: z.string(),\n where: z.optional(ConditionIR),\n within: z.optional(DurationIR),\n count: z.optional(z.number()),\n }),\n z.object({ ...conditionBase, type: z.literal('reachable'), channel: ChannelIR }),\n ])\n);\n\n/* --------------------------------- Triggers --------------------------------- */\n\n/**\n * Trigger shapes. The event trigger has two independent gates: `where` tests\n * the triggering event's payload (payload-only subtree, evaluated against the\n * incoming event before anything else), `filter` tests the user's profile.\n */\nexport const TriggerIR = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('event'),\n event: z.string(),\n where: z.optional(ConditionIR),\n filter: z.optional(ConditionIR),\n }),\n z.object({ type: z.literal('segment'), segment: z.string() }),\n z.object({ type: z.literal('date'), at: z.string() }),\n z.object({ type: z.literal('webhook') }),\n]);\nexport type TriggerIR = z.infer<typeof TriggerIR>;\n\n/* ----------------------------------- Nodes ---------------------------------- */\n\ninterface NodeBaseIR {\n /** Stable id derived from the structural path (rules in the file header). */\n id: string;\n /** Optional node name: UI title / observability handle (branch's optional first argument lands here). */\n label?: string | undefined;\n /** Metadata (provenance); excluded from contentHash. */\n meta?: NodeMetaIR | undefined;\n}\n\nexport type NodeIR =\n | (NodeBaseIR & {\n type: 'message';\n channel: ChannelIR;\n template: string;\n props: Record<string, PropValueIR>;\n /**\n * Push only: which of the user's devices get a copy. Absent means every\n * device the directory lists; 'latest' only the most recently registered.\n */\n devices?: 'latest' | undefined;\n })\n | (NodeBaseIR & { type: 'delay'; duration: DurationIR })\n | (NodeBaseIR & { type: 'random_delay'; min: DurationIR; max: DurationIR })\n | (NodeBaseIR & {\n type: 'time_window';\n days: WeekdayIR[];\n between: [string, string];\n tz: string;\n })\n | (NodeBaseIR & {\n type: 'wait_until';\n condition: ConditionIR;\n timeout: DurationIR;\n onTimeout: 'continue' | 'exit' | NodeIR[];\n })\n | (NodeBaseIR & {\n type: 'branch';\n cases: { label?: string | undefined; condition: ConditionIR; flow: NodeIR[] }[];\n /** Default arm (the DSL's bare tail argument). Absent = fall through to the main line. */\n otherwise?: NodeIR[] | undefined;\n })\n | (NodeBaseIR & {\n type: 'filter';\n /** Audit-log line for the users this gate drops. Metadata: excluded from contentHash. */\n reason?: string | undefined;\n condition: ConditionIR;\n })\n | (NodeBaseIR & {\n type: 'cohort';\n /**\n * Explicit experiment key: bucketing hashes `userId:key` instead of the\n * structural node id, so the assignment survives node insertion/moves and\n * the experiment keeps one identity across workflow versions. Absent →\n * the node id is used (fine for one-off splits).\n */\n key?: string | undefined;\n /**\n * Arms in authoring order — the order the interpreter accumulates weights\n * in, so it decides which bucket range each arm owns. The DSL keeps that\n * promise by rejecting integer-like arm names, which JavaScript would\n * hoist to the front of the object in numeric order. Weights sum to 100.\n */\n arms: { name: string; weight: number; flow: NodeIR[] }[];\n })\n | (NodeBaseIR & {\n /** `reason` is the audit-log line. Metadata: excluded from contentHash. */\n type: 'exit';\n reason?: string | undefined;\n })\n | (NodeBaseIR & { type: 'send_event'; event: string; payload: Record<string, PropValueIR> })\n | (NodeBaseIR & {\n type: 'action';\n /** Registry name of the custom action; the code itself lives in the deployed Worker bundle. */\n action: string;\n /** Argument values; user_property references are resolved at run time, like message props. */\n args: Record<string, PropValueIR>;\n });\n\nconst nodeBase = { id: z.string(), label: z.optional(z.string()), meta: z.optional(NodeMetaIR) };\n\nexport const NodeIR: z.ZodMiniType<NodeIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({\n ...nodeBase,\n type: z.literal('message'),\n channel: ChannelIR,\n template: z.string(),\n props: z.record(z.string(), PropValueIR),\n devices: z.optional(z.literal('latest')),\n }),\n z.object({ ...nodeBase, type: z.literal('delay'), duration: DurationIR }),\n z.object({ ...nodeBase, type: z.literal('random_delay'), min: DurationIR, max: DurationIR }),\n z.object({\n ...nodeBase,\n type: z.literal('time_window'),\n days: z.array(WeekdayIR),\n between: z.tuple([z.string(), z.string()]),\n tz: z.string(),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('wait_until'),\n condition: ConditionIR,\n timeout: DurationIR,\n onTimeout: z.union([z.literal('continue'), z.literal('exit'), z.array(NodeIR)]),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('branch'),\n cases: z.array(\n z.object({\n label: z.optional(z.string()),\n condition: ConditionIR,\n flow: z.array(NodeIR),\n })\n ),\n otherwise: z.optional(z.array(NodeIR)),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('filter'),\n condition: ConditionIR,\n reason: z.optional(z.string()),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('cohort'),\n key: z.optional(z.string()),\n arms: z.array(z.object({ name: z.string(), weight: z.number(), flow: z.array(NodeIR) })),\n }),\n z.object({ ...nodeBase, type: z.literal('exit'), reason: z.optional(z.string()) }),\n z.object({\n ...nodeBase,\n type: z.literal('send_event'),\n event: z.string(),\n payload: z.record(z.string(), PropValueIR),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('action'),\n action: z.string(),\n args: z.record(z.string(), PropValueIR),\n }),\n ])\n);\n\n/* ---------------------- Top-level definitions and bundle --------------------- */\n\nexport const GoalIR = z.object({\n condition: ConditionIR,\n within: z.optional(DurationIR),\n exitOnMatch: z.boolean(),\n});\nexport type GoalIR = z.infer<typeof GoalIR>;\n\n/**\n * Human-facing metadata: **excluded from contentHash** (see hash.ts).\n * Editing a name or description does not touch execution semantics, so it never\n * invalidates the version in-flight users are pinned to, nor shows up in plan.\n */\nexport const MetaIR = z.object({\n /**\n * Human label. The asset's `id` is its identity — a wire key that routing\n * tables and the entry ledger are built on — so it is not something to\n * rename for readability. This is: it is metadata, dropped before hashing,\n * and the studio shows it in place of the key wherever it is set.\n */\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n loc: z.optional(SourceLocIR),\n});\nexport type MetaIR = z.infer<typeof MetaIR>;\n\nexport const WorkflowIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`workflow({ id })`): routing tables, the entry ledger and reporting are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n meta: z.optional(MetaIR),\n trigger: TriggerIR,\n goal: z.optional(GoalIR),\n exitWhen: z.optional(ConditionIR),\n flow: z.array(NodeIR),\n});\nexport type WorkflowIR = z.infer<typeof WorkflowIR>;\n\nexport const SegmentIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`segment({ id })`): segment references and the membership store are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n /** Provenance plus the human label — MetaIR, same as a workflow's. */\n meta: z.optional(MetaIR),\n condition: ConditionIR,\n});\nexport type SegmentIR = z.infer<typeof SegmentIR>;\n\n/** Template manifest entry: IR records only the reference; the body lives in the template system. */\nexport const TemplateIR = z.object({\n irVersion: z.literal(IR_VERSION),\n key: z.string(),\n channel: ChannelIR,\n});\nexport type TemplateIR = z.infer<typeof TemplateIR>;\n\n/**\n * Action manifest entry: IR records the name; the implementation solidifies\n * into the Worker bundle at deploy time, never into IR (custom code stays out\n * of the data plane by design).\n */\nexport const ActionIR = z.object({\n irVersion: z.literal(IR_VERSION),\n name: z.string(),\n});\nexport type ActionIR = z.infer<typeof ActionIR>;\n\n/**\n * Deployment unit: the complete snapshot one `deploy` produces (terraform\n * apply, same mental model). The server diffs each definition's contentHash to\n * decide publish / skip / retire.\n */\nexport const BundleIR = z.object({\n irVersion: z.literal(IR_VERSION),\n workflows: z.array(WorkflowIR),\n segments: z.array(SegmentIR),\n templates: z.array(TemplateIR),\n actions: z.array(ActionIR),\n});\nexport type BundleIR = z.infer<typeof BundleIR>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ir.cjs","names":["z"],"sources":["../src/ir.ts"],"sourcesContent":["import * as z from 'zod/mini';\n\n/**\n * IR (Intermediate Representation) — what the DSL compiles to: serializable\n * JSON. It is the three-way contract between the engine that interprets it,\n * the UI (react-flow) that renders it, and diff / audit tooling.\n *\n * Validation strategy: the zod/mini schemas are the authoritative definition.\n * TS types are either inferred from a schema or hand-written under the same\n * name (zod cannot infer recursive types; the hand-written type is anchored\n * with a ZodMiniType<T> annotation, so any drift fails to compile). IR crosses\n * process boundaries (database, network, UI), so runtime validation is a must.\n *\n * ## Versioning (two independent axes)\n *\n * 1. IR format version (irVersion): evolution of the IR schema itself. Adding\n * optional fields does not bump it; only structurally incompatible changes\n * do (changing a discriminant, dropping a field, altering semantics).\n * Readers dispatch on irVersion to the matching schema/migrator; writers\n * always write the current version.\n * 2. Content version (contentHash): a content-addressed id for a single\n * definition's **execution semantics** — the canonical-JSON hash after\n * metadata (meta / label / reason) is stripped, see hash.ts. It is used to:\n * - pin a version when a user enters, so an in-flight journey runs the\n * pinned version to completion (the default policy; compatible hot\n * updates are a future explicit-migration topic). Known exception:\n * segment conditions are resolved **by id at evaluation time** — a\n * segment redeploy changes behaviour of in-flight journeys that\n * reference it. Pinning covers the workflow's own structure; per-hash\n * segment snapshots are future work;\n * - diff on deploy: same hash means unchanged, skip publishing;\n * - audit: answer \"which version was this user on\" at any point.\n *\n * ## Node ids\n *\n * Derived from the structural path at compile time — stable and deterministic:\n * root level '0', '1', …; the j-th child of a branch's i-th case is\n * '{branchId}.c{i}.{j}', the default arm '{branchId}.o.{j}'; cohort arms use\n * the arm name '{cohortId}.{armName}.{j}'; a waitUntil timeout flow '{id}.t.{j}'.\n * Editing a node's parameters keeps its id; inserting a node shifts the ids of\n * its later siblings (a known trade-off — locating in-flight users relies on\n * the pinned version rather than cross-version id alignment, and cross-version\n * mapping is an explicit migrator's job).\n */\n\nexport const IR_VERSION = 2;\n\n/* -------------------------------- Base values ------------------------------- */\n\nexport const ScalarIR = z.union([z.string(), z.number(), z.boolean()]);\nexport type ScalarIR = z.infer<typeof ScalarIR>;\n\n/** Duration: `value` keeps the DSL literal ('23 hours', for display), `ms` is what the engine uses. */\n/*\n * TODO: `value` is hashed alongside `ms`, so '7 days' / '1 week' / '168 hours'\n * — identical to the engine, which only reads ms — produce three different\n * contentHashes. Rewording a duration therefore reports as a semantic change in\n * plan and repins in-flight users. Moving `value` out of the hash (it is a\n * display string) would fix it; deferred because it changes existing hashes.\n */\nexport const DurationIR = z.object({ value: z.string(), ms: z.number() });\nexport type DurationIR = z.infer<typeof DurationIR>;\n\n/** User-property reference — isomorphic to the DSL's UserPropertyRef once serialized (phantom type dropped). */\nexport const UserPropertyRefIR = z.object({\n type: z.literal('user_property'),\n path: z.string(),\n});\nexport type UserPropertyRefIR = z.infer<typeof UserPropertyRefIR>;\n\n/** A message prop / event payload value: either a literal or a user-property reference. */\nexport const PropValueIR = z.union([ScalarIR, UserPropertyRefIR]);\nexport type PropValueIR = z.infer<typeof PropValueIR>;\n\nexport const ChannelIR = z.enum(['email', 'sms', 'push', 'in_app', 'slack', 'discord', 'survey']);\nexport type ChannelIR = z.infer<typeof ChannelIR>;\n\nexport const WeekdayIR = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);\nexport type WeekdayIR = z.infer<typeof WeekdayIR>;\n\n/* --------------------------------- Provenance -------------------------------- */\n\n/**\n * Source location of the builder call that produced a definition — the IR's\n * source map. Lives under `meta`, so it is **excluded from contentHash**\n * (see hash.ts): provenance never affects execution identity or plan.\n * `file` is cwd-relative when compiled under Node, a URL under Vite dev.\n */\nexport const SourceLocIR = z.object({\n file: z.string(),\n line: z.number(),\n column: z.number(),\n});\nexport type SourceLocIR = z.infer<typeof SourceLocIR>;\n\n/** Node-level metadata: provenance only, for now. Excluded from contentHash. */\nexport const NodeMetaIR = z.object({\n loc: z.optional(SourceLocIR),\n});\nexport type NodeMetaIR = z.infer<typeof NodeMetaIR>;\n\n/* -------------------------------- Conditions -------------------------------- */\n\nexport const PropertyOperatorIR = z.enum([\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'between',\n 'not_between',\n 'in_array',\n 'not_in_array',\n 'exists',\n 'not_exists',\n 'contains',\n 'not_contains',\n]);\nexport type PropertyOperatorIR = z.infer<typeof PropertyOperatorIR>;\n\n/**\n * Condition expression tree. The shape of value/values follows `op`:\n * eq/ne/gt/gte/lt/lte/contains/not_contains → value; in_array/not_in_array →\n * values; between/not_between → values = [min, max]; exists/not_exists → neither.\n *\n * `payload` predicates test the payload of an event (dotted paths reach nested\n * fields). They are only valid inside a `where` subtree — `performed.where`\n * and the event trigger's `where` — where an event row is in scope; the\n * compiler (compileBundle) and the evaluator both enforce the placement.\n * TODO: runtime refinement narrowing by op.\n */\n/**\n * Provenance rides on conditions too, so the studio can point at the exact\n * `eq(...)` / `and(...)` that produced a node — same rule as nodes: `meta` is\n * dropped before hashing, so carrying it never affects execution identity.\n */\ninterface ConditionBaseIR {\n meta?: NodeMetaIR | undefined;\n}\n\nexport type ConditionIR =\n | (ConditionBaseIR & { type: 'and'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'or'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'not'; condition: ConditionIR })\n /** Reference a segment by id (defined in SegmentIR, versioned separately). */\n | (ConditionBaseIR & { type: 'segment'; segment: string })\n | (ConditionBaseIR & {\n type: 'property';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n /** Event payload predicate; `path` is dotted for nested fields ('tags.utm_source'). */\n type: 'payload';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n type: 'performed';\n event: string;\n /** Payload filter: only events matching it count (a payload-only subtree). */\n where?: ConditionIR | undefined;\n within?: DurationIR | undefined;\n count?: number | undefined;\n })\n /**\n * The user can be reached on the channel right now: for push, the host's\n * device directory lists at least one device; for the others, the channel's\n * recipient property (email, phone, …) is set.\n */\n | (ConditionBaseIR & { type: 'reachable'; channel: ChannelIR });\n\nconst conditionBase = { meta: z.optional(NodeMetaIR) };\n\nexport const ConditionIR: z.ZodMiniType<ConditionIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({ ...conditionBase, type: z.literal('and'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('or'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('not'), condition: ConditionIR }),\n z.object({ ...conditionBase, type: z.literal('segment'), segment: z.string() }),\n z.object({\n ...conditionBase,\n type: z.literal('property'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('payload'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('performed'),\n event: z.string(),\n where: z.optional(ConditionIR),\n within: z.optional(DurationIR),\n count: z.optional(z.number()),\n }),\n z.object({ ...conditionBase, type: z.literal('reachable'), channel: ChannelIR }),\n ])\n);\n\n/* --------------------------------- Triggers --------------------------------- */\n\n/**\n * Trigger shapes. The event trigger has two independent gates: `where` tests\n * the triggering event's payload (payload-only subtree, evaluated against the\n * incoming event before anything else), `filter` tests the user's profile.\n */\nexport const TriggerIR = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('event'),\n event: z.string(),\n where: z.optional(ConditionIR),\n filter: z.optional(ConditionIR),\n }),\n z.object({ type: z.literal('segment'), segment: z.string() }),\n z.object({ type: z.literal('date'), at: z.string() }),\n z.object({ type: z.literal('webhook') }),\n]);\nexport type TriggerIR = z.infer<typeof TriggerIR>;\n\n/* ----------------------------------- Nodes ---------------------------------- */\n\ninterface NodeBaseIR {\n /** Stable id derived from the structural path (rules in the file header). */\n id: string;\n /** Optional node name: UI title / observability handle (branch's optional first argument lands here). */\n label?: string | undefined;\n /** Metadata (provenance); excluded from contentHash. */\n meta?: NodeMetaIR | undefined;\n}\n\nexport type NodeIR =\n | (NodeBaseIR & {\n type: 'message';\n channel: ChannelIR;\n template: string;\n props: Record<string, PropValueIR>;\n /**\n * Push only: which of the user's devices get a copy. Absent means every\n * device the directory lists; 'latest' only the most recently registered.\n */\n devices?: 'latest' | undefined;\n /**\n * Email and push: the template's subscription topic, or null for a transactional message\n * (sent whatever the user opted out of). Absent for other channels, and in IR compiled\n * before topics existed: such a step checks the channel-level opt-out only, as it always did.\n */\n topic?: string | null | undefined;\n })\n | (NodeBaseIR & { type: 'delay'; duration: DurationIR })\n | (NodeBaseIR & { type: 'random_delay'; min: DurationIR; max: DurationIR })\n | (NodeBaseIR & {\n type: 'time_window';\n days: WeekdayIR[];\n between: [string, string];\n tz: string;\n })\n | (NodeBaseIR & {\n type: 'wait_until';\n condition: ConditionIR;\n timeout: DurationIR;\n onTimeout: 'continue' | 'exit' | NodeIR[];\n })\n | (NodeBaseIR & {\n type: 'branch';\n cases: { label?: string | undefined; condition: ConditionIR; flow: NodeIR[] }[];\n /** Default arm (the DSL's bare tail argument). Absent = fall through to the main line. */\n otherwise?: NodeIR[] | undefined;\n })\n | (NodeBaseIR & {\n type: 'filter';\n /** Audit-log line for the users this gate drops. Metadata: excluded from contentHash. */\n reason?: string | undefined;\n condition: ConditionIR;\n })\n | (NodeBaseIR & {\n type: 'cohort';\n /**\n * Explicit experiment key: bucketing hashes `userId:key` instead of the\n * structural node id, so the assignment survives node insertion/moves and\n * the experiment keeps one identity across workflow versions. Absent →\n * the node id is used (fine for one-off splits).\n */\n key?: string | undefined;\n /**\n * Arms in authoring order — the order the interpreter accumulates weights\n * in, so it decides which bucket range each arm owns. The DSL keeps that\n * promise by rejecting integer-like arm names, which JavaScript would\n * hoist to the front of the object in numeric order. Weights sum to 100.\n */\n arms: { name: string; weight: number; flow: NodeIR[] }[];\n })\n | (NodeBaseIR & {\n /** `reason` is the audit-log line. Metadata: excluded from contentHash. */\n type: 'exit';\n reason?: string | undefined;\n })\n | (NodeBaseIR & { type: 'send_event'; event: string; payload: Record<string, PropValueIR> })\n | (NodeBaseIR & {\n type: 'action';\n /** Registry name of the custom action; the code itself lives in the deployed Worker bundle. */\n action: string;\n /** Argument values; user_property references are resolved at run time, like message props. */\n args: Record<string, PropValueIR>;\n });\n\nconst nodeBase = { id: z.string(), label: z.optional(z.string()), meta: z.optional(NodeMetaIR) };\n\nexport const NodeIR: z.ZodMiniType<NodeIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({\n ...nodeBase,\n type: z.literal('message'),\n channel: ChannelIR,\n template: z.string(),\n props: z.record(z.string(), PropValueIR),\n devices: z.optional(z.literal('latest')),\n topic: z.optional(z.nullable(z.string())),\n }),\n z.object({ ...nodeBase, type: z.literal('delay'), duration: DurationIR }),\n z.object({ ...nodeBase, type: z.literal('random_delay'), min: DurationIR, max: DurationIR }),\n z.object({\n ...nodeBase,\n type: z.literal('time_window'),\n days: z.array(WeekdayIR),\n between: z.tuple([z.string(), z.string()]),\n tz: z.string(),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('wait_until'),\n condition: ConditionIR,\n timeout: DurationIR,\n onTimeout: z.union([z.literal('continue'), z.literal('exit'), z.array(NodeIR)]),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('branch'),\n cases: z.array(\n z.object({\n label: z.optional(z.string()),\n condition: ConditionIR,\n flow: z.array(NodeIR),\n })\n ),\n otherwise: z.optional(z.array(NodeIR)),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('filter'),\n condition: ConditionIR,\n reason: z.optional(z.string()),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('cohort'),\n key: z.optional(z.string()),\n arms: z.array(z.object({ name: z.string(), weight: z.number(), flow: z.array(NodeIR) })),\n }),\n z.object({ ...nodeBase, type: z.literal('exit'), reason: z.optional(z.string()) }),\n z.object({\n ...nodeBase,\n type: z.literal('send_event'),\n event: z.string(),\n payload: z.record(z.string(), PropValueIR),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('action'),\n action: z.string(),\n args: z.record(z.string(), PropValueIR),\n }),\n ])\n);\n\n/* ---------------------- Top-level definitions and bundle --------------------- */\n\nexport const GoalIR = z.object({\n condition: ConditionIR,\n within: z.optional(DurationIR),\n exitOnMatch: z.boolean(),\n});\nexport type GoalIR = z.infer<typeof GoalIR>;\n\n/**\n * Human-facing metadata: **excluded from contentHash** (see hash.ts).\n * Editing a name or description does not touch execution semantics, so it never\n * invalidates the version in-flight users are pinned to, nor shows up in plan.\n */\nexport const MetaIR = z.object({\n /**\n * Human label. The asset's `id` is its identity — a wire key that routing\n * tables and the entry ledger are built on — so it is not something to\n * rename for readability. This is: it is metadata, dropped before hashing,\n * and the studio shows it in place of the key wherever it is set.\n */\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n loc: z.optional(SourceLocIR),\n});\nexport type MetaIR = z.infer<typeof MetaIR>;\n\nexport const WorkflowIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`workflow({ id })`): routing tables, the entry ledger and reporting are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n meta: z.optional(MetaIR),\n trigger: TriggerIR,\n goal: z.optional(GoalIR),\n exitWhen: z.optional(ConditionIR),\n flow: z.array(NodeIR),\n});\nexport type WorkflowIR = z.infer<typeof WorkflowIR>;\n\nexport const SegmentIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`segment({ id })`): segment references and the membership store are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n /** Provenance plus the human label — MetaIR, same as a workflow's. */\n meta: z.optional(MetaIR),\n condition: ConditionIR,\n});\nexport type SegmentIR = z.infer<typeof SegmentIR>;\n\n/** Template manifest entry: IR records only the reference; the body lives in the template system. */\nexport const TemplateIR = z.object({\n irVersion: z.literal(IR_VERSION),\n key: z.string(),\n channel: ChannelIR,\n});\nexport type TemplateIR = z.infer<typeof TemplateIR>;\n\n/**\n * Action manifest entry: IR records the name; the implementation solidifies\n * into the Worker bundle at deploy time, never into IR (custom code stays out\n * of the data plane by design).\n */\nexport const ActionIR = z.object({\n irVersion: z.literal(IR_VERSION),\n name: z.string(),\n});\nexport type ActionIR = z.infer<typeof ActionIR>;\n\n/**\n * Deployment unit: the complete snapshot one `deploy` produces (terraform\n * apply, same mental model). The server diffs each definition's contentHash to\n * decide publish / skip / retire.\n */\n/**\n * The subscription topics the contract declares, carried by the bundle so the engine validates\n * `/subscriptions` and the templates' topics against the deployed list, not the SDK's word.\n */\nexport const SubscriptionsIR = z.object({\n topics: z.array(z.string()),\n});\nexport type SubscriptionsIR = z.infer<typeof SubscriptionsIR>;\n\nexport const BundleIR = z.object({\n irVersion: z.literal(IR_VERSION),\n workflows: z.array(WorkflowIR),\n segments: z.array(SegmentIR),\n templates: z.array(TemplateIR),\n actions: z.array(ActionIR),\n /** Absent in a bundle compiled before topics existed: no topics. */\n subscriptions: z.optional(SubscriptionsIR),\n});\nexport type BundleIR = z.infer<typeof BundleIR>;\n"],"mappings":"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"}
package/dist/ir.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as z from "zod/mini";
2
- //#region src/ir.d.ts
3
2
  /**
4
3
  * IR (Intermediate Representation) — what the DSL compiles to: serializable
5
4
  * JSON. It is the three-way contract between the engine that interprets it,
@@ -223,6 +222,12 @@ export type NodeIR = (NodeBaseIR & {
223
222
  * device the directory lists; 'latest' only the most recently registered.
224
223
  */
225
224
  devices?: 'latest' | undefined;
225
+ /**
226
+ * Email and push: the template's subscription topic, or null for a transactional message
227
+ * (sent whatever the user opted out of). Absent for other channels, and in IR compiled
228
+ * before topics existed: such a step checks the channel-level opt-out only, as it always did.
229
+ */
230
+ topic?: string | null | undefined;
226
231
  }) | (NodeBaseIR & {
227
232
  type: 'delay';
228
233
  duration: DurationIR;
@@ -399,6 +404,14 @@ export type ActionIR = z.infer<typeof ActionIR>;
399
404
  * apply, same mental model). The server diffs each definition's contentHash to
400
405
  * decide publish / skip / retire.
401
406
  */
407
+ /**
408
+ * The subscription topics the contract declares, carried by the bundle so the engine validates
409
+ * `/subscriptions` and the templates' topics against the deployed list, not the SDK's word.
410
+ */
411
+ export declare const SubscriptionsIR: z.ZodMiniObject<{
412
+ topics: z.ZodMiniArray<z.ZodMiniString<string>>;
413
+ }, z.core.$strip>;
414
+ export type SubscriptionsIR = z.infer<typeof SubscriptionsIR>;
402
415
  export declare const BundleIR: z.ZodMiniObject<{
403
416
  irVersion: z.ZodMiniLiteral<2>;
404
417
  workflows: z.ZodMiniArray<z.ZodMiniObject<{
@@ -471,8 +484,10 @@ export declare const BundleIR: z.ZodMiniObject<{
471
484
  irVersion: z.ZodMiniLiteral<2>;
472
485
  name: z.ZodMiniString<string>;
473
486
  }, z.core.$strip>>;
487
+ subscriptions: z.ZodMiniOptional<z.ZodMiniObject<{
488
+ topics: z.ZodMiniArray<z.ZodMiniString<string>>;
489
+ }, z.core.$strip>>;
474
490
  }, z.core.$strip>;
475
491
  export type BundleIR = z.infer<typeof BundleIR>;
476
- //#endregion
477
492
  export {};
478
493
  //# sourceMappingURL=ir.d.cts.map
package/dist/ir.d.cts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.cts","names":[],"sources":["../src/ir.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6Ca;qBAIA,UAAQ,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA;YACT,WAAW,EAAE,aAAa;;qBAUzB,YAAU,EAAA;;;GAAkD,EAAA,KAAA;YAC7D,aAAa,EAAE,aAAa;;qBAG3B,mBAAiB,EAAA;;;GAG5B,EAAA,KAAA;YACU,oBAAoB,EAAE,aAAa;;qBAGlC,aAAW,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,2BAAA,EAAA;;;GAAyC,EAAA,KAAA;YACrD,cAAc,EAAE,aAAa;qBAE5B,WAAS,EAAA;;;;;;;;;YACV,YAAY,EAAE,aAAa;qBAE1B,WAAS,EAAA;;;;;;;;;YACV,YAAY,EAAE,aAAa;;;;;;;qBAU1B,aAAW,EAAA;;;;GAItB,EAAA,KAAA;YACU,cAAc,EAAE,aAAa;;qBAG5B,YAAU,EAAA;;;;;;GAErB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;qBAI3B,oBAAkB,EAAA;;;;;;;;;;;;;;;;YAgBnB,qBAAqB,EAAE,aAAa;;;;;;;;;;;;;;;;;UAkBtC;EACR,OAAO;;YAGG,eACP;EAAoB;EAAa,YAAY;MAC7C;EAAoB;EAAY,YAAY;MAC5C;EAAoB;EAAa,WAAW;;;CAE5C;EAAoB;EAAiB;MACrC;EACC;EACA;EACA,IAAI;EACJ,QAAQ;EACR,SAAS;MAEV;;EAEC;EACA;EACA,IAAI;EACJ,QAAQ;EACR,SAAS;MAEV;EACC;EACA;;EAEA,QAAQ;EACR,SAAS;EACT;;;;;;;CAOD;EAAoB;EAAmB,SAAS;;qBAIxC,aAAa,EAAE,YAAY;;;;;;qBAyC3B,WAAS,EAAA,2BAAA,EAAA;;;;;;;;;;;;;GAUpB,EAAA,KAAA;YACU,YAAY,EAAE,aAAa;UAI7B;;EAER;;EAEA;;EAEA,OAAO;;YAGG,UACP;EACC;EACA,SAAS;EACT;EACA,OAAO,eAAe;;;;;EAKtB;MAED;EAAe;EAAe,UAAU;MACxC;EAAe;EAAsB,KAAK;EAAY,KAAK;MAC3D;EACC;EACA,MAAM;EACN;EACA;MAED;EACC;EACA,WAAW;EACX,SAAS;EACT,iCAAiC;MAElC;EACC;EACA;IAAS;IAA4B,WAAW;IAAa,MAAM;;;EAEnE,YAAY;MAEb;EACC;;EAEA;EACA,WAAW;MAEZ;EACC;;;;;;;EAOA;;;;;;;EAOA;IAAQ;IAAc;IAAgB,MAAM;;MAE7C;;EAEC;EACA;MAED;EAAe;EAAoB;EAAe,SAAS,eAAe;MAC1E;EACC;;EAEA;;EAEA,MAAM,eAAe;;qBAKd,QAAQ,EAAE,YAAY;qBAoEtB,QAAM,EAAA;;;;;;;GAIjB,EAAA,KAAA;YACU,SAAS,EAAE,aAAa;;;;;;qBAOvB,QAAM,EAAA;;;;;;;;GAUjB,EAAA,KAAA;YACU,SAAS,EAAE,aAAa;qBAEvB,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAUrB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;qBAE3B,WAAS,EAAA;;;;;;;;;;;;;;GAQpB,EAAA,KAAA;YACU,YAAY,EAAE,aAAa;;qBAG1B,YAAU,EAAA;;;;;;;;;;;;GAIrB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;;;;;;qBAO3B,UAAQ,EAAA;;;GAGnB,EAAA,KAAA;YACU,WAAW,EAAE,aAAa;;;;;;qBAOzB,UAAQ,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAMnB,EAAA,KAAA;YACU,WAAW,EAAE,aAAa"}
1
+ {"version":3,"file":"ir.d.cts","names":[],"sources":["../src/ir.ts"],"mappings":"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"}
package/dist/ir.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as z from "zod/mini";
2
- //#region src/ir.d.ts
3
2
  /**
4
3
  * IR (Intermediate Representation) — what the DSL compiles to: serializable
5
4
  * JSON. It is the three-way contract between the engine that interprets it,
@@ -223,6 +222,12 @@ export type NodeIR = (NodeBaseIR & {
223
222
  * device the directory lists; 'latest' only the most recently registered.
224
223
  */
225
224
  devices?: 'latest' | undefined;
225
+ /**
226
+ * Email and push: the template's subscription topic, or null for a transactional message
227
+ * (sent whatever the user opted out of). Absent for other channels, and in IR compiled
228
+ * before topics existed: such a step checks the channel-level opt-out only, as it always did.
229
+ */
230
+ topic?: string | null | undefined;
226
231
  }) | (NodeBaseIR & {
227
232
  type: 'delay';
228
233
  duration: DurationIR;
@@ -399,6 +404,14 @@ export type ActionIR = z.infer<typeof ActionIR>;
399
404
  * apply, same mental model). The server diffs each definition's contentHash to
400
405
  * decide publish / skip / retire.
401
406
  */
407
+ /**
408
+ * The subscription topics the contract declares, carried by the bundle so the engine validates
409
+ * `/subscriptions` and the templates' topics against the deployed list, not the SDK's word.
410
+ */
411
+ export declare const SubscriptionsIR: z.ZodMiniObject<{
412
+ topics: z.ZodMiniArray<z.ZodMiniString<string>>;
413
+ }, z.core.$strip>;
414
+ export type SubscriptionsIR = z.infer<typeof SubscriptionsIR>;
402
415
  export declare const BundleIR: z.ZodMiniObject<{
403
416
  irVersion: z.ZodMiniLiteral<2>;
404
417
  workflows: z.ZodMiniArray<z.ZodMiniObject<{
@@ -471,8 +484,10 @@ export declare const BundleIR: z.ZodMiniObject<{
471
484
  irVersion: z.ZodMiniLiteral<2>;
472
485
  name: z.ZodMiniString<string>;
473
486
  }, z.core.$strip>>;
487
+ subscriptions: z.ZodMiniOptional<z.ZodMiniObject<{
488
+ topics: z.ZodMiniArray<z.ZodMiniString<string>>;
489
+ }, z.core.$strip>>;
474
490
  }, z.core.$strip>;
475
491
  export type BundleIR = z.infer<typeof BundleIR>;
476
- //#endregion
477
492
  export {};
478
493
  //# sourceMappingURL=ir.d.mts.map
package/dist/ir.d.mts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.mts","names":[],"sources":["../src/ir.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6Ca;qBAIA,UAAQ,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA;YACT,WAAW,EAAE,aAAa;;qBAUzB,YAAU,EAAA;;;GAAkD,EAAA,KAAA;YAC7D,aAAa,EAAE,aAAa;;qBAG3B,mBAAiB,EAAA;;;GAG5B,EAAA,KAAA;YACU,oBAAoB,EAAE,aAAa;;qBAGlC,aAAW,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,2BAAA,EAAA;;;GAAyC,EAAA,KAAA;YACrD,cAAc,EAAE,aAAa;qBAE5B,WAAS,EAAA;;;;;;;;;YACV,YAAY,EAAE,aAAa;qBAE1B,WAAS,EAAA;;;;;;;;;YACV,YAAY,EAAE,aAAa;;;;;;;qBAU1B,aAAW,EAAA;;;;GAItB,EAAA,KAAA;YACU,cAAc,EAAE,aAAa;;qBAG5B,YAAU,EAAA;;;;;;GAErB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;qBAI3B,oBAAkB,EAAA;;;;;;;;;;;;;;;;YAgBnB,qBAAqB,EAAE,aAAa;;;;;;;;;;;;;;;;;UAkBtC;EACR,OAAO;;YAGG,eACP;EAAoB;EAAa,YAAY;MAC7C;EAAoB;EAAY,YAAY;MAC5C;EAAoB;EAAa,WAAW;;;CAE5C;EAAoB;EAAiB;MACrC;EACC;EACA;EACA,IAAI;EACJ,QAAQ;EACR,SAAS;MAEV;;EAEC;EACA;EACA,IAAI;EACJ,QAAQ;EACR,SAAS;MAEV;EACC;EACA;;EAEA,QAAQ;EACR,SAAS;EACT;;;;;;;CAOD;EAAoB;EAAmB,SAAS;;qBAIxC,aAAa,EAAE,YAAY;;;;;;qBAyC3B,WAAS,EAAA,2BAAA,EAAA;;;;;;;;;;;;;GAUpB,EAAA,KAAA;YACU,YAAY,EAAE,aAAa;UAI7B;;EAER;;EAEA;;EAEA,OAAO;;YAGG,UACP;EACC;EACA,SAAS;EACT;EACA,OAAO,eAAe;;;;;EAKtB;MAED;EAAe;EAAe,UAAU;MACxC;EAAe;EAAsB,KAAK;EAAY,KAAK;MAC3D;EACC;EACA,MAAM;EACN;EACA;MAED;EACC;EACA,WAAW;EACX,SAAS;EACT,iCAAiC;MAElC;EACC;EACA;IAAS;IAA4B,WAAW;IAAa,MAAM;;;EAEnE,YAAY;MAEb;EACC;;EAEA;EACA,WAAW;MAEZ;EACC;;;;;;;EAOA;;;;;;;EAOA;IAAQ;IAAc;IAAgB,MAAM;;MAE7C;;EAEC;EACA;MAED;EAAe;EAAoB;EAAe,SAAS,eAAe;MAC1E;EACC;;EAEA;;EAEA,MAAM,eAAe;;qBAKd,QAAQ,EAAE,YAAY;qBAoEtB,QAAM,EAAA;;;;;;;GAIjB,EAAA,KAAA;YACU,SAAS,EAAE,aAAa;;;;;;qBAOvB,QAAM,EAAA;;;;;;;;GAUjB,EAAA,KAAA;YACU,SAAS,EAAE,aAAa;qBAEvB,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAUrB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;qBAE3B,WAAS,EAAA;;;;;;;;;;;;;;GAQpB,EAAA,KAAA;YACU,YAAY,EAAE,aAAa;;qBAG1B,YAAU,EAAA;;;;;;;;;;;;GAIrB,EAAA,KAAA;YACU,aAAa,EAAE,aAAa;;;;;;qBAO3B,UAAQ,EAAA;;;GAGnB,EAAA,KAAA;YACU,WAAW,EAAE,aAAa;;;;;;qBAOzB,UAAQ,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAMnB,EAAA,KAAA;YACU,WAAW,EAAE,aAAa"}
1
+ {"version":3,"file":"ir.d.mts","names":[],"sources":["../src/ir.ts"],"mappings":"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"}
package/dist/ir.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as z from "zod/mini";
2
- //#region src/ir.ts
2
+ // src/ir.ts
3
3
  /**
4
4
  * IR (Intermediate Representation) — what the DSL compiles to: serializable
5
5
  * JSON. It is the three-way contract between the engine that interprets it,
@@ -193,7 +193,8 @@ const NodeIR = z.lazy(() => z.discriminatedUnion("type", [
193
193
  channel: ChannelIR,
194
194
  template: z.string(),
195
195
  props: z.record(z.string(), PropValueIR),
196
- devices: z.optional(z.literal("latest"))
196
+ devices: z.optional(z.literal("latest")),
197
+ topic: z.optional(z.nullable(z.string()))
197
198
  }),
198
199
  z.object({
199
200
  ...nodeBase,
@@ -329,14 +330,20 @@ const ActionIR = z.object({
329
330
  * apply, same mental model). The server diffs each definition's contentHash to
330
331
  * decide publish / skip / retire.
331
332
  */
333
+ /**
334
+ * The subscription topics the contract declares, carried by the bundle so the engine validates
335
+ * `/subscriptions` and the templates' topics against the deployed list, not the SDK's word.
336
+ */
337
+ const SubscriptionsIR = z.object({ topics: z.array(z.string()) });
332
338
  const BundleIR = z.object({
333
339
  irVersion: z.literal(2),
334
340
  workflows: z.array(WorkflowIR),
335
341
  segments: z.array(SegmentIR),
336
342
  templates: z.array(TemplateIR),
337
- actions: z.array(ActionIR)
343
+ actions: z.array(ActionIR),
344
+ /** Absent in a bundle compiled before topics existed: no topics. */
345
+ subscriptions: z.optional(SubscriptionsIR)
338
346
  });
339
- //#endregion
340
- export { ActionIR, BundleIR, ChannelIR, ConditionIR, DurationIR, GoalIR, IR_VERSION, MetaIR, NodeIR, NodeMetaIR, PropValueIR, PropertyOperatorIR, ScalarIR, SegmentIR, SourceLocIR, TemplateIR, TriggerIR, UserPropertyRefIR, WeekdayIR, WorkflowIR };
347
+ export { ActionIR, BundleIR, ChannelIR, ConditionIR, DurationIR, GoalIR, IR_VERSION, MetaIR, NodeIR, NodeMetaIR, PropValueIR, PropertyOperatorIR, ScalarIR, SegmentIR, SourceLocIR, SubscriptionsIR, TemplateIR, TriggerIR, UserPropertyRefIR, WeekdayIR, WorkflowIR };
341
348
 
342
349
  //# sourceMappingURL=ir.mjs.map
package/dist/ir.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.mjs","names":[],"sources":["../src/ir.ts"],"sourcesContent":["import * as z from 'zod/mini';\n\n/**\n * IR (Intermediate Representation) — what the DSL compiles to: serializable\n * JSON. It is the three-way contract between the engine that interprets it,\n * the UI (react-flow) that renders it, and diff / audit tooling.\n *\n * Validation strategy: the zod/mini schemas are the authoritative definition.\n * TS types are either inferred from a schema or hand-written under the same\n * name (zod cannot infer recursive types; the hand-written type is anchored\n * with a ZodMiniType<T> annotation, so any drift fails to compile). IR crosses\n * process boundaries (database, network, UI), so runtime validation is a must.\n *\n * ## Versioning (two independent axes)\n *\n * 1. IR format version (irVersion): evolution of the IR schema itself. Adding\n * optional fields does not bump it; only structurally incompatible changes\n * do (changing a discriminant, dropping a field, altering semantics).\n * Readers dispatch on irVersion to the matching schema/migrator; writers\n * always write the current version.\n * 2. Content version (contentHash): a content-addressed id for a single\n * definition's **execution semantics** — the canonical-JSON hash after\n * metadata (meta / label / reason) is stripped, see hash.ts. It is used to:\n * - pin a version when a user enters, so an in-flight journey runs the\n * pinned version to completion (the default policy; compatible hot\n * updates are a future explicit-migration topic). Known exception:\n * segment conditions are resolved **by id at evaluation time** — a\n * segment redeploy changes behaviour of in-flight journeys that\n * reference it. Pinning covers the workflow's own structure; per-hash\n * segment snapshots are future work;\n * - diff on deploy: same hash means unchanged, skip publishing;\n * - audit: answer \"which version was this user on\" at any point.\n *\n * ## Node ids\n *\n * Derived from the structural path at compile time — stable and deterministic:\n * root level '0', '1', …; the j-th child of a branch's i-th case is\n * '{branchId}.c{i}.{j}', the default arm '{branchId}.o.{j}'; cohort arms use\n * the arm name '{cohortId}.{armName}.{j}'; a waitUntil timeout flow '{id}.t.{j}'.\n * Editing a node's parameters keeps its id; inserting a node shifts the ids of\n * its later siblings (a known trade-off — locating in-flight users relies on\n * the pinned version rather than cross-version id alignment, and cross-version\n * mapping is an explicit migrator's job).\n */\n\nexport const IR_VERSION = 2;\n\n/* -------------------------------- Base values ------------------------------- */\n\nexport const ScalarIR = z.union([z.string(), z.number(), z.boolean()]);\nexport type ScalarIR = z.infer<typeof ScalarIR>;\n\n/** Duration: `value` keeps the DSL literal ('23 hours', for display), `ms` is what the engine uses. */\n/*\n * TODO: `value` is hashed alongside `ms`, so '7 days' / '1 week' / '168 hours'\n * — identical to the engine, which only reads ms — produce three different\n * contentHashes. Rewording a duration therefore reports as a semantic change in\n * plan and repins in-flight users. Moving `value` out of the hash (it is a\n * display string) would fix it; deferred because it changes existing hashes.\n */\nexport const DurationIR = z.object({ value: z.string(), ms: z.number() });\nexport type DurationIR = z.infer<typeof DurationIR>;\n\n/** User-property reference — isomorphic to the DSL's UserPropertyRef once serialized (phantom type dropped). */\nexport const UserPropertyRefIR = z.object({\n type: z.literal('user_property'),\n path: z.string(),\n});\nexport type UserPropertyRefIR = z.infer<typeof UserPropertyRefIR>;\n\n/** A message prop / event payload value: either a literal or a user-property reference. */\nexport const PropValueIR = z.union([ScalarIR, UserPropertyRefIR]);\nexport type PropValueIR = z.infer<typeof PropValueIR>;\n\nexport const ChannelIR = z.enum(['email', 'sms', 'push', 'in_app', 'slack', 'discord', 'survey']);\nexport type ChannelIR = z.infer<typeof ChannelIR>;\n\nexport const WeekdayIR = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);\nexport type WeekdayIR = z.infer<typeof WeekdayIR>;\n\n/* --------------------------------- Provenance -------------------------------- */\n\n/**\n * Source location of the builder call that produced a definition — the IR's\n * source map. Lives under `meta`, so it is **excluded from contentHash**\n * (see hash.ts): provenance never affects execution identity or plan.\n * `file` is cwd-relative when compiled under Node, a URL under Vite dev.\n */\nexport const SourceLocIR = z.object({\n file: z.string(),\n line: z.number(),\n column: z.number(),\n});\nexport type SourceLocIR = z.infer<typeof SourceLocIR>;\n\n/** Node-level metadata: provenance only, for now. Excluded from contentHash. */\nexport const NodeMetaIR = z.object({\n loc: z.optional(SourceLocIR),\n});\nexport type NodeMetaIR = z.infer<typeof NodeMetaIR>;\n\n/* -------------------------------- Conditions -------------------------------- */\n\nexport const PropertyOperatorIR = z.enum([\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'between',\n 'not_between',\n 'in_array',\n 'not_in_array',\n 'exists',\n 'not_exists',\n 'contains',\n 'not_contains',\n]);\nexport type PropertyOperatorIR = z.infer<typeof PropertyOperatorIR>;\n\n/**\n * Condition expression tree. The shape of value/values follows `op`:\n * eq/ne/gt/gte/lt/lte/contains/not_contains → value; in_array/not_in_array →\n * values; between/not_between → values = [min, max]; exists/not_exists → neither.\n *\n * `payload` predicates test the payload of an event (dotted paths reach nested\n * fields). They are only valid inside a `where` subtree — `performed.where`\n * and the event trigger's `where` — where an event row is in scope; the\n * compiler (compileBundle) and the evaluator both enforce the placement.\n * TODO: runtime refinement narrowing by op.\n */\n/**\n * Provenance rides on conditions too, so the studio can point at the exact\n * `eq(...)` / `and(...)` that produced a node — same rule as nodes: `meta` is\n * dropped before hashing, so carrying it never affects execution identity.\n */\ninterface ConditionBaseIR {\n meta?: NodeMetaIR | undefined;\n}\n\nexport type ConditionIR =\n | (ConditionBaseIR & { type: 'and'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'or'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'not'; condition: ConditionIR })\n /** Reference a segment by id (defined in SegmentIR, versioned separately). */\n | (ConditionBaseIR & { type: 'segment'; segment: string })\n | (ConditionBaseIR & {\n type: 'property';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n /** Event payload predicate; `path` is dotted for nested fields ('tags.utm_source'). */\n type: 'payload';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n type: 'performed';\n event: string;\n /** Payload filter: only events matching it count (a payload-only subtree). */\n where?: ConditionIR | undefined;\n within?: DurationIR | undefined;\n count?: number | undefined;\n })\n /**\n * The user can be reached on the channel right now: for push, the host's\n * device directory lists at least one device; for the others, the channel's\n * recipient property (email, phone, …) is set.\n */\n | (ConditionBaseIR & { type: 'reachable'; channel: ChannelIR });\n\nconst conditionBase = { meta: z.optional(NodeMetaIR) };\n\nexport const ConditionIR: z.ZodMiniType<ConditionIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({ ...conditionBase, type: z.literal('and'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('or'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('not'), condition: ConditionIR }),\n z.object({ ...conditionBase, type: z.literal('segment'), segment: z.string() }),\n z.object({\n ...conditionBase,\n type: z.literal('property'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('payload'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('performed'),\n event: z.string(),\n where: z.optional(ConditionIR),\n within: z.optional(DurationIR),\n count: z.optional(z.number()),\n }),\n z.object({ ...conditionBase, type: z.literal('reachable'), channel: ChannelIR }),\n ])\n);\n\n/* --------------------------------- Triggers --------------------------------- */\n\n/**\n * Trigger shapes. The event trigger has two independent gates: `where` tests\n * the triggering event's payload (payload-only subtree, evaluated against the\n * incoming event before anything else), `filter` tests the user's profile.\n */\nexport const TriggerIR = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('event'),\n event: z.string(),\n where: z.optional(ConditionIR),\n filter: z.optional(ConditionIR),\n }),\n z.object({ type: z.literal('segment'), segment: z.string() }),\n z.object({ type: z.literal('date'), at: z.string() }),\n z.object({ type: z.literal('webhook') }),\n]);\nexport type TriggerIR = z.infer<typeof TriggerIR>;\n\n/* ----------------------------------- Nodes ---------------------------------- */\n\ninterface NodeBaseIR {\n /** Stable id derived from the structural path (rules in the file header). */\n id: string;\n /** Optional node name: UI title / observability handle (branch's optional first argument lands here). */\n label?: string | undefined;\n /** Metadata (provenance); excluded from contentHash. */\n meta?: NodeMetaIR | undefined;\n}\n\nexport type NodeIR =\n | (NodeBaseIR & {\n type: 'message';\n channel: ChannelIR;\n template: string;\n props: Record<string, PropValueIR>;\n /**\n * Push only: which of the user's devices get a copy. Absent means every\n * device the directory lists; 'latest' only the most recently registered.\n */\n devices?: 'latest' | undefined;\n })\n | (NodeBaseIR & { type: 'delay'; duration: DurationIR })\n | (NodeBaseIR & { type: 'random_delay'; min: DurationIR; max: DurationIR })\n | (NodeBaseIR & {\n type: 'time_window';\n days: WeekdayIR[];\n between: [string, string];\n tz: string;\n })\n | (NodeBaseIR & {\n type: 'wait_until';\n condition: ConditionIR;\n timeout: DurationIR;\n onTimeout: 'continue' | 'exit' | NodeIR[];\n })\n | (NodeBaseIR & {\n type: 'branch';\n cases: { label?: string | undefined; condition: ConditionIR; flow: NodeIR[] }[];\n /** Default arm (the DSL's bare tail argument). Absent = fall through to the main line. */\n otherwise?: NodeIR[] | undefined;\n })\n | (NodeBaseIR & {\n type: 'filter';\n /** Audit-log line for the users this gate drops. Metadata: excluded from contentHash. */\n reason?: string | undefined;\n condition: ConditionIR;\n })\n | (NodeBaseIR & {\n type: 'cohort';\n /**\n * Explicit experiment key: bucketing hashes `userId:key` instead of the\n * structural node id, so the assignment survives node insertion/moves and\n * the experiment keeps one identity across workflow versions. Absent →\n * the node id is used (fine for one-off splits).\n */\n key?: string | undefined;\n /**\n * Arms in authoring order — the order the interpreter accumulates weights\n * in, so it decides which bucket range each arm owns. The DSL keeps that\n * promise by rejecting integer-like arm names, which JavaScript would\n * hoist to the front of the object in numeric order. Weights sum to 100.\n */\n arms: { name: string; weight: number; flow: NodeIR[] }[];\n })\n | (NodeBaseIR & {\n /** `reason` is the audit-log line. Metadata: excluded from contentHash. */\n type: 'exit';\n reason?: string | undefined;\n })\n | (NodeBaseIR & { type: 'send_event'; event: string; payload: Record<string, PropValueIR> })\n | (NodeBaseIR & {\n type: 'action';\n /** Registry name of the custom action; the code itself lives in the deployed Worker bundle. */\n action: string;\n /** Argument values; user_property references are resolved at run time, like message props. */\n args: Record<string, PropValueIR>;\n });\n\nconst nodeBase = { id: z.string(), label: z.optional(z.string()), meta: z.optional(NodeMetaIR) };\n\nexport const NodeIR: z.ZodMiniType<NodeIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({\n ...nodeBase,\n type: z.literal('message'),\n channel: ChannelIR,\n template: z.string(),\n props: z.record(z.string(), PropValueIR),\n devices: z.optional(z.literal('latest')),\n }),\n z.object({ ...nodeBase, type: z.literal('delay'), duration: DurationIR }),\n z.object({ ...nodeBase, type: z.literal('random_delay'), min: DurationIR, max: DurationIR }),\n z.object({\n ...nodeBase,\n type: z.literal('time_window'),\n days: z.array(WeekdayIR),\n between: z.tuple([z.string(), z.string()]),\n tz: z.string(),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('wait_until'),\n condition: ConditionIR,\n timeout: DurationIR,\n onTimeout: z.union([z.literal('continue'), z.literal('exit'), z.array(NodeIR)]),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('branch'),\n cases: z.array(\n z.object({\n label: z.optional(z.string()),\n condition: ConditionIR,\n flow: z.array(NodeIR),\n })\n ),\n otherwise: z.optional(z.array(NodeIR)),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('filter'),\n condition: ConditionIR,\n reason: z.optional(z.string()),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('cohort'),\n key: z.optional(z.string()),\n arms: z.array(z.object({ name: z.string(), weight: z.number(), flow: z.array(NodeIR) })),\n }),\n z.object({ ...nodeBase, type: z.literal('exit'), reason: z.optional(z.string()) }),\n z.object({\n ...nodeBase,\n type: z.literal('send_event'),\n event: z.string(),\n payload: z.record(z.string(), PropValueIR),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('action'),\n action: z.string(),\n args: z.record(z.string(), PropValueIR),\n }),\n ])\n);\n\n/* ---------------------- Top-level definitions and bundle --------------------- */\n\nexport const GoalIR = z.object({\n condition: ConditionIR,\n within: z.optional(DurationIR),\n exitOnMatch: z.boolean(),\n});\nexport type GoalIR = z.infer<typeof GoalIR>;\n\n/**\n * Human-facing metadata: **excluded from contentHash** (see hash.ts).\n * Editing a name or description does not touch execution semantics, so it never\n * invalidates the version in-flight users are pinned to, nor shows up in plan.\n */\nexport const MetaIR = z.object({\n /**\n * Human label. The asset's `id` is its identity — a wire key that routing\n * tables and the entry ledger are built on — so it is not something to\n * rename for readability. This is: it is metadata, dropped before hashing,\n * and the studio shows it in place of the key wherever it is set.\n */\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n loc: z.optional(SourceLocIR),\n});\nexport type MetaIR = z.infer<typeof MetaIR>;\n\nexport const WorkflowIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`workflow({ id })`): routing tables, the entry ledger and reporting are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n meta: z.optional(MetaIR),\n trigger: TriggerIR,\n goal: z.optional(GoalIR),\n exitWhen: z.optional(ConditionIR),\n flow: z.array(NodeIR),\n});\nexport type WorkflowIR = z.infer<typeof WorkflowIR>;\n\nexport const SegmentIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`segment({ id })`): segment references and the membership store are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n /** Provenance plus the human label — MetaIR, same as a workflow's. */\n meta: z.optional(MetaIR),\n condition: ConditionIR,\n});\nexport type SegmentIR = z.infer<typeof SegmentIR>;\n\n/** Template manifest entry: IR records only the reference; the body lives in the template system. */\nexport const TemplateIR = z.object({\n irVersion: z.literal(IR_VERSION),\n key: z.string(),\n channel: ChannelIR,\n});\nexport type TemplateIR = z.infer<typeof TemplateIR>;\n\n/**\n * Action manifest entry: IR records the name; the implementation solidifies\n * into the Worker bundle at deploy time, never into IR (custom code stays out\n * of the data plane by design).\n */\nexport const ActionIR = z.object({\n irVersion: z.literal(IR_VERSION),\n name: z.string(),\n});\nexport type ActionIR = z.infer<typeof ActionIR>;\n\n/**\n * Deployment unit: the complete snapshot one `deploy` produces (terraform\n * apply, same mental model). The server diffs each definition's contentHash to\n * decide publish / skip / retire.\n */\nexport const BundleIR = z.object({\n irVersion: z.literal(IR_VERSION),\n workflows: z.array(WorkflowIR),\n segments: z.array(SegmentIR),\n templates: z.array(TemplateIR),\n actions: z.array(ActionIR),\n});\nexport type BundleIR = z.infer<typeof BundleIR>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ir.mjs","names":[],"sources":["../src/ir.ts"],"sourcesContent":["import * as z from 'zod/mini';\n\n/**\n * IR (Intermediate Representation) — what the DSL compiles to: serializable\n * JSON. It is the three-way contract between the engine that interprets it,\n * the UI (react-flow) that renders it, and diff / audit tooling.\n *\n * Validation strategy: the zod/mini schemas are the authoritative definition.\n * TS types are either inferred from a schema or hand-written under the same\n * name (zod cannot infer recursive types; the hand-written type is anchored\n * with a ZodMiniType<T> annotation, so any drift fails to compile). IR crosses\n * process boundaries (database, network, UI), so runtime validation is a must.\n *\n * ## Versioning (two independent axes)\n *\n * 1. IR format version (irVersion): evolution of the IR schema itself. Adding\n * optional fields does not bump it; only structurally incompatible changes\n * do (changing a discriminant, dropping a field, altering semantics).\n * Readers dispatch on irVersion to the matching schema/migrator; writers\n * always write the current version.\n * 2. Content version (contentHash): a content-addressed id for a single\n * definition's **execution semantics** — the canonical-JSON hash after\n * metadata (meta / label / reason) is stripped, see hash.ts. It is used to:\n * - pin a version when a user enters, so an in-flight journey runs the\n * pinned version to completion (the default policy; compatible hot\n * updates are a future explicit-migration topic). Known exception:\n * segment conditions are resolved **by id at evaluation time** — a\n * segment redeploy changes behaviour of in-flight journeys that\n * reference it. Pinning covers the workflow's own structure; per-hash\n * segment snapshots are future work;\n * - diff on deploy: same hash means unchanged, skip publishing;\n * - audit: answer \"which version was this user on\" at any point.\n *\n * ## Node ids\n *\n * Derived from the structural path at compile time — stable and deterministic:\n * root level '0', '1', …; the j-th child of a branch's i-th case is\n * '{branchId}.c{i}.{j}', the default arm '{branchId}.o.{j}'; cohort arms use\n * the arm name '{cohortId}.{armName}.{j}'; a waitUntil timeout flow '{id}.t.{j}'.\n * Editing a node's parameters keeps its id; inserting a node shifts the ids of\n * its later siblings (a known trade-off — locating in-flight users relies on\n * the pinned version rather than cross-version id alignment, and cross-version\n * mapping is an explicit migrator's job).\n */\n\nexport const IR_VERSION = 2;\n\n/* -------------------------------- Base values ------------------------------- */\n\nexport const ScalarIR = z.union([z.string(), z.number(), z.boolean()]);\nexport type ScalarIR = z.infer<typeof ScalarIR>;\n\n/** Duration: `value` keeps the DSL literal ('23 hours', for display), `ms` is what the engine uses. */\n/*\n * TODO: `value` is hashed alongside `ms`, so '7 days' / '1 week' / '168 hours'\n * — identical to the engine, which only reads ms — produce three different\n * contentHashes. Rewording a duration therefore reports as a semantic change in\n * plan and repins in-flight users. Moving `value` out of the hash (it is a\n * display string) would fix it; deferred because it changes existing hashes.\n */\nexport const DurationIR = z.object({ value: z.string(), ms: z.number() });\nexport type DurationIR = z.infer<typeof DurationIR>;\n\n/** User-property reference — isomorphic to the DSL's UserPropertyRef once serialized (phantom type dropped). */\nexport const UserPropertyRefIR = z.object({\n type: z.literal('user_property'),\n path: z.string(),\n});\nexport type UserPropertyRefIR = z.infer<typeof UserPropertyRefIR>;\n\n/** A message prop / event payload value: either a literal or a user-property reference. */\nexport const PropValueIR = z.union([ScalarIR, UserPropertyRefIR]);\nexport type PropValueIR = z.infer<typeof PropValueIR>;\n\nexport const ChannelIR = z.enum(['email', 'sms', 'push', 'in_app', 'slack', 'discord', 'survey']);\nexport type ChannelIR = z.infer<typeof ChannelIR>;\n\nexport const WeekdayIR = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);\nexport type WeekdayIR = z.infer<typeof WeekdayIR>;\n\n/* --------------------------------- Provenance -------------------------------- */\n\n/**\n * Source location of the builder call that produced a definition — the IR's\n * source map. Lives under `meta`, so it is **excluded from contentHash**\n * (see hash.ts): provenance never affects execution identity or plan.\n * `file` is cwd-relative when compiled under Node, a URL under Vite dev.\n */\nexport const SourceLocIR = z.object({\n file: z.string(),\n line: z.number(),\n column: z.number(),\n});\nexport type SourceLocIR = z.infer<typeof SourceLocIR>;\n\n/** Node-level metadata: provenance only, for now. Excluded from contentHash. */\nexport const NodeMetaIR = z.object({\n loc: z.optional(SourceLocIR),\n});\nexport type NodeMetaIR = z.infer<typeof NodeMetaIR>;\n\n/* -------------------------------- Conditions -------------------------------- */\n\nexport const PropertyOperatorIR = z.enum([\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'between',\n 'not_between',\n 'in_array',\n 'not_in_array',\n 'exists',\n 'not_exists',\n 'contains',\n 'not_contains',\n]);\nexport type PropertyOperatorIR = z.infer<typeof PropertyOperatorIR>;\n\n/**\n * Condition expression tree. The shape of value/values follows `op`:\n * eq/ne/gt/gte/lt/lte/contains/not_contains → value; in_array/not_in_array →\n * values; between/not_between → values = [min, max]; exists/not_exists → neither.\n *\n * `payload` predicates test the payload of an event (dotted paths reach nested\n * fields). They are only valid inside a `where` subtree — `performed.where`\n * and the event trigger's `where` — where an event row is in scope; the\n * compiler (compileBundle) and the evaluator both enforce the placement.\n * TODO: runtime refinement narrowing by op.\n */\n/**\n * Provenance rides on conditions too, so the studio can point at the exact\n * `eq(...)` / `and(...)` that produced a node — same rule as nodes: `meta` is\n * dropped before hashing, so carrying it never affects execution identity.\n */\ninterface ConditionBaseIR {\n meta?: NodeMetaIR | undefined;\n}\n\nexport type ConditionIR =\n | (ConditionBaseIR & { type: 'and'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'or'; conditions: ConditionIR[] })\n | (ConditionBaseIR & { type: 'not'; condition: ConditionIR })\n /** Reference a segment by id (defined in SegmentIR, versioned separately). */\n | (ConditionBaseIR & { type: 'segment'; segment: string })\n | (ConditionBaseIR & {\n type: 'property';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n /** Event payload predicate; `path` is dotted for nested fields ('tags.utm_source'). */\n type: 'payload';\n path: string;\n op: PropertyOperatorIR;\n value?: ScalarIR | undefined;\n values?: ScalarIR[] | undefined;\n })\n | (ConditionBaseIR & {\n type: 'performed';\n event: string;\n /** Payload filter: only events matching it count (a payload-only subtree). */\n where?: ConditionIR | undefined;\n within?: DurationIR | undefined;\n count?: number | undefined;\n })\n /**\n * The user can be reached on the channel right now: for push, the host's\n * device directory lists at least one device; for the others, the channel's\n * recipient property (email, phone, …) is set.\n */\n | (ConditionBaseIR & { type: 'reachable'; channel: ChannelIR });\n\nconst conditionBase = { meta: z.optional(NodeMetaIR) };\n\nexport const ConditionIR: z.ZodMiniType<ConditionIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({ ...conditionBase, type: z.literal('and'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('or'), conditions: z.array(ConditionIR) }),\n z.object({ ...conditionBase, type: z.literal('not'), condition: ConditionIR }),\n z.object({ ...conditionBase, type: z.literal('segment'), segment: z.string() }),\n z.object({\n ...conditionBase,\n type: z.literal('property'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('payload'),\n path: z.string(),\n op: PropertyOperatorIR,\n value: z.optional(ScalarIR),\n values: z.optional(z.array(ScalarIR)),\n }),\n z.object({\n ...conditionBase,\n type: z.literal('performed'),\n event: z.string(),\n where: z.optional(ConditionIR),\n within: z.optional(DurationIR),\n count: z.optional(z.number()),\n }),\n z.object({ ...conditionBase, type: z.literal('reachable'), channel: ChannelIR }),\n ])\n);\n\n/* --------------------------------- Triggers --------------------------------- */\n\n/**\n * Trigger shapes. The event trigger has two independent gates: `where` tests\n * the triggering event's payload (payload-only subtree, evaluated against the\n * incoming event before anything else), `filter` tests the user's profile.\n */\nexport const TriggerIR = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('event'),\n event: z.string(),\n where: z.optional(ConditionIR),\n filter: z.optional(ConditionIR),\n }),\n z.object({ type: z.literal('segment'), segment: z.string() }),\n z.object({ type: z.literal('date'), at: z.string() }),\n z.object({ type: z.literal('webhook') }),\n]);\nexport type TriggerIR = z.infer<typeof TriggerIR>;\n\n/* ----------------------------------- Nodes ---------------------------------- */\n\ninterface NodeBaseIR {\n /** Stable id derived from the structural path (rules in the file header). */\n id: string;\n /** Optional node name: UI title / observability handle (branch's optional first argument lands here). */\n label?: string | undefined;\n /** Metadata (provenance); excluded from contentHash. */\n meta?: NodeMetaIR | undefined;\n}\n\nexport type NodeIR =\n | (NodeBaseIR & {\n type: 'message';\n channel: ChannelIR;\n template: string;\n props: Record<string, PropValueIR>;\n /**\n * Push only: which of the user's devices get a copy. Absent means every\n * device the directory lists; 'latest' only the most recently registered.\n */\n devices?: 'latest' | undefined;\n /**\n * Email and push: the template's subscription topic, or null for a transactional message\n * (sent whatever the user opted out of). Absent for other channels, and in IR compiled\n * before topics existed: such a step checks the channel-level opt-out only, as it always did.\n */\n topic?: string | null | undefined;\n })\n | (NodeBaseIR & { type: 'delay'; duration: DurationIR })\n | (NodeBaseIR & { type: 'random_delay'; min: DurationIR; max: DurationIR })\n | (NodeBaseIR & {\n type: 'time_window';\n days: WeekdayIR[];\n between: [string, string];\n tz: string;\n })\n | (NodeBaseIR & {\n type: 'wait_until';\n condition: ConditionIR;\n timeout: DurationIR;\n onTimeout: 'continue' | 'exit' | NodeIR[];\n })\n | (NodeBaseIR & {\n type: 'branch';\n cases: { label?: string | undefined; condition: ConditionIR; flow: NodeIR[] }[];\n /** Default arm (the DSL's bare tail argument). Absent = fall through to the main line. */\n otherwise?: NodeIR[] | undefined;\n })\n | (NodeBaseIR & {\n type: 'filter';\n /** Audit-log line for the users this gate drops. Metadata: excluded from contentHash. */\n reason?: string | undefined;\n condition: ConditionIR;\n })\n | (NodeBaseIR & {\n type: 'cohort';\n /**\n * Explicit experiment key: bucketing hashes `userId:key` instead of the\n * structural node id, so the assignment survives node insertion/moves and\n * the experiment keeps one identity across workflow versions. Absent →\n * the node id is used (fine for one-off splits).\n */\n key?: string | undefined;\n /**\n * Arms in authoring order — the order the interpreter accumulates weights\n * in, so it decides which bucket range each arm owns. The DSL keeps that\n * promise by rejecting integer-like arm names, which JavaScript would\n * hoist to the front of the object in numeric order. Weights sum to 100.\n */\n arms: { name: string; weight: number; flow: NodeIR[] }[];\n })\n | (NodeBaseIR & {\n /** `reason` is the audit-log line. Metadata: excluded from contentHash. */\n type: 'exit';\n reason?: string | undefined;\n })\n | (NodeBaseIR & { type: 'send_event'; event: string; payload: Record<string, PropValueIR> })\n | (NodeBaseIR & {\n type: 'action';\n /** Registry name of the custom action; the code itself lives in the deployed Worker bundle. */\n action: string;\n /** Argument values; user_property references are resolved at run time, like message props. */\n args: Record<string, PropValueIR>;\n });\n\nconst nodeBase = { id: z.string(), label: z.optional(z.string()), meta: z.optional(NodeMetaIR) };\n\nexport const NodeIR: z.ZodMiniType<NodeIR> = z.lazy(() =>\n z.discriminatedUnion('type', [\n z.object({\n ...nodeBase,\n type: z.literal('message'),\n channel: ChannelIR,\n template: z.string(),\n props: z.record(z.string(), PropValueIR),\n devices: z.optional(z.literal('latest')),\n topic: z.optional(z.nullable(z.string())),\n }),\n z.object({ ...nodeBase, type: z.literal('delay'), duration: DurationIR }),\n z.object({ ...nodeBase, type: z.literal('random_delay'), min: DurationIR, max: DurationIR }),\n z.object({\n ...nodeBase,\n type: z.literal('time_window'),\n days: z.array(WeekdayIR),\n between: z.tuple([z.string(), z.string()]),\n tz: z.string(),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('wait_until'),\n condition: ConditionIR,\n timeout: DurationIR,\n onTimeout: z.union([z.literal('continue'), z.literal('exit'), z.array(NodeIR)]),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('branch'),\n cases: z.array(\n z.object({\n label: z.optional(z.string()),\n condition: ConditionIR,\n flow: z.array(NodeIR),\n })\n ),\n otherwise: z.optional(z.array(NodeIR)),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('filter'),\n condition: ConditionIR,\n reason: z.optional(z.string()),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('cohort'),\n key: z.optional(z.string()),\n arms: z.array(z.object({ name: z.string(), weight: z.number(), flow: z.array(NodeIR) })),\n }),\n z.object({ ...nodeBase, type: z.literal('exit'), reason: z.optional(z.string()) }),\n z.object({\n ...nodeBase,\n type: z.literal('send_event'),\n event: z.string(),\n payload: z.record(z.string(), PropValueIR),\n }),\n z.object({\n ...nodeBase,\n type: z.literal('action'),\n action: z.string(),\n args: z.record(z.string(), PropValueIR),\n }),\n ])\n);\n\n/* ---------------------- Top-level definitions and bundle --------------------- */\n\nexport const GoalIR = z.object({\n condition: ConditionIR,\n within: z.optional(DurationIR),\n exitOnMatch: z.boolean(),\n});\nexport type GoalIR = z.infer<typeof GoalIR>;\n\n/**\n * Human-facing metadata: **excluded from contentHash** (see hash.ts).\n * Editing a name or description does not touch execution semantics, so it never\n * invalidates the version in-flight users are pinned to, nor shows up in plan.\n */\nexport const MetaIR = z.object({\n /**\n * Human label. The asset's `id` is its identity — a wire key that routing\n * tables and the entry ledger are built on — so it is not something to\n * rename for readability. This is: it is metadata, dropped before hashing,\n * and the studio shows it in place of the key wherever it is set.\n */\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n loc: z.optional(SourceLocIR),\n});\nexport type MetaIR = z.infer<typeof MetaIR>;\n\nexport const WorkflowIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`workflow({ id })`): routing tables, the entry ledger and reporting are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n meta: z.optional(MetaIR),\n trigger: TriggerIR,\n goal: z.optional(GoalIR),\n exitWhen: z.optional(ConditionIR),\n flow: z.array(NodeIR),\n});\nexport type WorkflowIR = z.infer<typeof WorkflowIR>;\n\nexport const SegmentIR = z.object({\n irVersion: z.literal(IR_VERSION),\n /** Wire identity (`segment({ id })`): segment references and the membership store are keyed on it. */\n id: z.string(),\n contentHash: z.string(),\n /** Provenance plus the human label — MetaIR, same as a workflow's. */\n meta: z.optional(MetaIR),\n condition: ConditionIR,\n});\nexport type SegmentIR = z.infer<typeof SegmentIR>;\n\n/** Template manifest entry: IR records only the reference; the body lives in the template system. */\nexport const TemplateIR = z.object({\n irVersion: z.literal(IR_VERSION),\n key: z.string(),\n channel: ChannelIR,\n});\nexport type TemplateIR = z.infer<typeof TemplateIR>;\n\n/**\n * Action manifest entry: IR records the name; the implementation solidifies\n * into the Worker bundle at deploy time, never into IR (custom code stays out\n * of the data plane by design).\n */\nexport const ActionIR = z.object({\n irVersion: z.literal(IR_VERSION),\n name: z.string(),\n});\nexport type ActionIR = z.infer<typeof ActionIR>;\n\n/**\n * Deployment unit: the complete snapshot one `deploy` produces (terraform\n * apply, same mental model). The server diffs each definition's contentHash to\n * decide publish / skip / retire.\n */\n/**\n * The subscription topics the contract declares, carried by the bundle so the engine validates\n * `/subscriptions` and the templates' topics against the deployed list, not the SDK's word.\n */\nexport const SubscriptionsIR = z.object({\n topics: z.array(z.string()),\n});\nexport type SubscriptionsIR = z.infer<typeof SubscriptionsIR>;\n\nexport const BundleIR = z.object({\n irVersion: z.literal(IR_VERSION),\n workflows: z.array(WorkflowIR),\n segments: z.array(SegmentIR),\n templates: z.array(TemplateIR),\n actions: z.array(ActionIR),\n /** Absent in a bundle compiled before topics existed: no topics. */\n subscriptions: z.optional(SubscriptionsIR),\n});\nexport type BundleIR = z.infer<typeof BundleIR>;\n"],"mappings":"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"}
package/dist/jwt.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let node_buffer = require("node:buffer");
3
- //#region src/jwt.ts
3
+ // src/jwt.ts
4
4
  /**
5
5
  * The byte-level helpers the token signers share (`fcm.ts`, `apns.ts`, `webpush.ts`): JWT
6
6
  * base64url and PEM → DER for WebCrypto's `importKey('pkcs8', …)`.
@@ -11,7 +11,6 @@ function pemToDer(pem) {
11
11
  const der = node_buffer.Buffer.from(body, "base64");
12
12
  return der.buffer.slice(der.byteOffset, der.byteOffset + der.byteLength);
13
13
  }
14
- //#endregion
15
14
  exports.base64url = base64url;
16
15
  exports.pemToDer = pemToDer;
17
16
 
package/dist/jwt.d.cts CHANGED
@@ -1,9 +1,7 @@
1
- //#region src/jwt.d.ts
2
1
  /**
3
2
  * The byte-level helpers the token signers share (`fcm.ts`, `apns.ts`, `webpush.ts`): JWT
4
3
  * base64url and PEM → DER for WebCrypto's `importKey('pkcs8', …)`.
5
4
  */
6
5
  export declare const base64url: (bytes: Uint8Array | string) => string;
7
6
  export declare function pemToDer(pem: string): ArrayBuffer;
8
- //#endregion
9
7
  //# sourceMappingURL=jwt.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.cts","names":[],"sources":["../src/jwt.ts"],"mappings":";;;;;qBAOa,YAAS,OAAW;wBAGjB,SAAS,cAAc"}
1
+ {"version":3,"file":"jwt.d.cts","names":[],"sources":["../src/jwt.ts"],"mappings":";;;;qBAOa,YAAS,OAAW;wBAGjB,SAAS,cAAc"}
package/dist/jwt.d.mts CHANGED
@@ -1,9 +1,7 @@
1
- //#region src/jwt.d.ts
2
1
  /**
3
2
  * The byte-level helpers the token signers share (`fcm.ts`, `apns.ts`, `webpush.ts`): JWT
4
3
  * base64url and PEM → DER for WebCrypto's `importKey('pkcs8', …)`.
5
4
  */
6
5
  export declare const base64url: (bytes: Uint8Array | string) => string;
7
6
  export declare function pemToDer(pem: string): ArrayBuffer;
8
- //#endregion
9
7
  //# sourceMappingURL=jwt.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.mts","names":[],"sources":["../src/jwt.ts"],"mappings":";;;;;qBAOa,YAAS,OAAW;wBAGjB,SAAS,cAAc"}
1
+ {"version":3,"file":"jwt.d.mts","names":[],"sources":["../src/jwt.ts"],"mappings":";;;;qBAOa,YAAS,OAAW;wBAGjB,SAAS,cAAc"}
package/dist/jwt.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Buffer } from "node:buffer";
2
- //#region src/jwt.ts
2
+ // src/jwt.ts
3
3
  /**
4
4
  * The byte-level helpers the token signers share (`fcm.ts`, `apns.ts`, `webpush.ts`): JWT
5
5
  * base64url and PEM → DER for WebCrypto's `importKey('pkcs8', …)`.
@@ -10,7 +10,6 @@ function pemToDer(pem) {
10
10
  const der = Buffer.from(body, "base64");
11
11
  return der.buffer.slice(der.byteOffset, der.byteOffset + der.byteLength);
12
12
  }
13
- //#endregion
14
13
  export { base64url, pemToDer };
15
14
 
16
15
  //# sourceMappingURL=jwt.mjs.map
package/dist/plan.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_hash = require("./hash.cjs");
3
- //#region src/plan.ts
3
+ // src/plan.ts
4
4
  /** Whether a status warrants human attention (metadata-only edits do not). */
5
5
  function isSemanticChange(status) {
6
6
  return status === "added" || status === "removed" || status === "changed";
@@ -210,7 +210,6 @@ function plan(local, deployed) {
210
210
  ].some((change) => isSemanticChange(change.status))
211
211
  };
212
212
  }
213
- //#endregion
214
213
  exports.isSemanticChange = isSemanticChange;
215
214
  exports.plan = plan;
216
215
 
package/dist/plan.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { BundleIR, NodeIR } from "./ir.cjs";
2
- //#region src/plan.d.ts
3
2
  /**
4
3
  * Plan — the diff between local definitions and what is deployed (terraform
5
4
  * plan, same mental model).
@@ -64,5 +63,4 @@ export interface BundlePlan {
64
63
  * if (changes.hasChanges) { ... }
65
64
  */
66
65
  export declare function plan(local: BundleIR, deployed?: BundleIR): BundlePlan;
67
- //#endregion
68
66
  //# sourceMappingURL=plan.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.cts","names":[],"sources":["../src/plan.ts"],"mappings":";;;;;;;;;;;;;;;;;YAmBY;;wBAGI,iBAAiB,QAAQ;iBAIxB;EACf;EACA;;EAEA,MAAM;;iBAGS;;EAEf;EACA,QAAQ;;EAER;;EAEA;;EAEA;;;;;;;EAOA,OAAO;;iBAGQ;;EAEf;EACA,QAAQ;EACR;EACA;;iBAGe;EACf,WAAW;EACX,UAAU;EACV,WAAW;EACX,SAAS;;EAET;;;;;;;;wBA2Nc,KAAK,OAAO,UAAU,WAAW,WAAW"}
1
+ {"version":3,"file":"plan.d.cts","names":[],"sources":["../src/plan.ts"],"mappings":";;;;;;;;;;;;;;;;YAmBY;;wBAGI,iBAAiB,QAAQ;iBAIxB;EACf;EACA;;EAEA,MAAM;;iBAGS;;EAEf;EACA,QAAQ;;EAER;;EAEA;;EAEA;;;;;;;EAOA,OAAO;;iBAGQ;;EAEf;EACA,QAAQ;EACR;EACA;;iBAGe;EACf,WAAW;EACX,UAAU;EACV,WAAW;EACX,SAAS;;EAET;;;;;;;;wBA2Nc,KAAK,OAAO,UAAU,WAAW,WAAW"}
package/dist/plan.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { BundleIR, NodeIR } from "./ir.mjs";
2
- //#region src/plan.d.ts
3
2
  /**
4
3
  * Plan — the diff between local definitions and what is deployed (terraform
5
4
  * plan, same mental model).
@@ -64,5 +63,4 @@ export interface BundlePlan {
64
63
  * if (changes.hasChanges) { ... }
65
64
  */
66
65
  export declare function plan(local: BundleIR, deployed?: BundleIR): BundlePlan;
67
- //#endregion
68
66
  //# sourceMappingURL=plan.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.mts","names":[],"sources":["../src/plan.ts"],"mappings":";;;;;;;;;;;;;;;;;YAmBY;;wBAGI,iBAAiB,QAAQ;iBAIxB;EACf;EACA;;EAEA,MAAM;;iBAGS;;EAEf;EACA,QAAQ;;EAER;;EAEA;;EAEA;;;;;;;EAOA,OAAO;;iBAGQ;;EAEf;EACA,QAAQ;EACR;EACA;;iBAGe;EACf,WAAW;EACX,UAAU;EACV,WAAW;EACX,SAAS;;EAET;;;;;;;;wBA2Nc,KAAK,OAAO,UAAU,WAAW,WAAW"}
1
+ {"version":3,"file":"plan.d.mts","names":[],"sources":["../src/plan.ts"],"mappings":";;;;;;;;;;;;;;;;YAmBY;;wBAGI,iBAAiB,QAAQ;iBAIxB;EACf;EACA;;EAEA,MAAM;;iBAGS;;EAEf;EACA,QAAQ;;EAER;;EAEA;;EAEA;;;;;;;EAOA,OAAO;;iBAGQ;;EAEf;EACA,QAAQ;EACR;EACA;;iBAGe;EACf,WAAW;EACX,UAAU;EACV,WAAW;EACX,SAAS;;EAET;;;;;;;;wBA2Nc,KAAK,OAAO,UAAU,WAAW,WAAW"}
package/dist/plan.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { fullHash, stripMeta, stripProvenance } from "./hash.mjs";
2
- //#region src/plan.ts
2
+ // src/plan.ts
3
3
  /** Whether a status warrants human attention (metadata-only edits do not). */
4
4
  function isSemanticChange(status) {
5
5
  return status === "added" || status === "removed" || status === "changed";
@@ -209,7 +209,6 @@ function plan(local, deployed) {
209
209
  ].some((change) => isSemanticChange(change.status))
210
210
  };
211
211
  }
212
- //#endregion
213
212
  export { isSemanticChange, plan };
214
213
 
215
214
  //# sourceMappingURL=plan.mjs.map
@@ -3,7 +3,7 @@ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
3
3
  const require_store_postgres = require("./store/postgres.cjs");
4
4
  let postgres = require("postgres");
5
5
  postgres = require_runtime.__toESM(postgres, 1);
6
- //#region src/postgres-js.ts
6
+ // src/postgres-js.ts
7
7
  /**
8
8
  * `@shware/workflow/postgres-js` — the Postgres store over postgres.js
9
9
  * (`postgres` is an optional peer dependency; import this subpath only when
@@ -35,7 +35,6 @@ function postgresJsStore(connectionString, options = {}) {
35
35
  close: () => sql.end({ timeout: 5 })
36
36
  };
37
37
  }
38
- //#endregion
39
38
  exports.postgresJsClient = postgresJsClient;
40
39
  exports.postgresJsStore = postgresJsStore;
41
40
 
@@ -2,7 +2,6 @@ import { SqlClientLike } from "./store/sql.cjs";
2
2
  import { PostgresJourneyStoreOptions } from "./store/postgres.cjs";
3
3
  import { StoreLease } from "./store/index.cjs";
4
4
  import postgres from "postgres";
5
- //#region src/postgres-js.d.ts
6
5
  /**
7
6
  * `@shware/workflow/postgres-js` — the Postgres store over postgres.js
8
7
  * (`postgres` is an optional peer dependency; import this subpath only when
@@ -24,5 +23,4 @@ export interface PostgresJsStoreOptions extends PostgresJourneyStoreOptions {
24
23
  * and Hyperdrive keeps the real pool next to the database.
25
24
  */
26
25
  export declare function postgresJsStore(connectionString: string, options?: PostgresJsStoreOptions): Required<StoreLease>;
27
- //#endregion
28
26
  //# sourceMappingURL=postgres-js.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-js.d.cts","names":[],"sources":["../src/postgres-js.ts"],"mappings":";;;;;;;;;;;wBAegB,iBACd,KAAK,SAAS,MAAM,SAAS,gBAC7B,0BACC;iBAWc,+BAA+B;;;;;;EAM9C,aAAa,SAAS,QAAQ;;;;;;;wBAQhB,gBACd,0BACA,UAAS,yBACR,SAAS"}
1
+ {"version":3,"file":"postgres-js.d.cts","names":[],"sources":["../src/postgres-js.ts"],"mappings":";;;;;;;;;;wBAegB,iBACd,KAAK,SAAS,MAAM,SAAS,gBAC7B,0BACC;iBAWc,+BAA+B;;;;;;EAM9C,aAAa,SAAS,QAAQ;;;;;;;wBAQhB,gBACd,0BACA,UAAS,yBACR,SAAS"}
@@ -2,7 +2,6 @@ import { SqlClientLike } from "./store/sql.mjs";
2
2
  import { PostgresJourneyStoreOptions } from "./store/postgres.mjs";
3
3
  import { StoreLease } from "./store/index.mjs";
4
4
  import postgres from "postgres";
5
- //#region src/postgres-js.d.ts
6
5
  /**
7
6
  * `@shware/workflow/postgres-js` — the Postgres store over postgres.js
8
7
  * (`postgres` is an optional peer dependency; import this subpath only when
@@ -24,5 +23,4 @@ export interface PostgresJsStoreOptions extends PostgresJourneyStoreOptions {
24
23
  * and Hyperdrive keeps the real pool next to the database.
25
24
  */
26
25
  export declare function postgresJsStore(connectionString: string, options?: PostgresJsStoreOptions): Required<StoreLease>;
27
- //#endregion
28
26
  //# sourceMappingURL=postgres-js.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-js.d.mts","names":[],"sources":["../src/postgres-js.ts"],"mappings":";;;;;;;;;;;wBAegB,iBACd,KAAK,SAAS,MAAM,SAAS,gBAC7B,0BACC;iBAWc,+BAA+B;;;;;;EAM9C,aAAa,SAAS,QAAQ;;;;;;;wBAQhB,gBACd,0BACA,UAAS,yBACR,SAAS"}
1
+ {"version":3,"file":"postgres-js.d.mts","names":[],"sources":["../src/postgres-js.ts"],"mappings":";;;;;;;;;;wBAegB,iBACd,KAAK,SAAS,MAAM,SAAS,gBAC7B,0BACC;iBAWc,+BAA+B;;;;;;EAM9C,aAAa,SAAS,QAAQ;;;;;;;wBAQhB,gBACd,0BACA,UAAS,yBACR,SAAS"}
@@ -1,6 +1,6 @@
1
1
  import { PostgresJourneyStore } from "./store/postgres.mjs";
2
2
  import postgres from "postgres";
3
- //#region src/postgres-js.ts
3
+ // src/postgres-js.ts
4
4
  /**
5
5
  * `@shware/workflow/postgres-js` — the Postgres store over postgres.js
6
6
  * (`postgres` is an optional peer dependency; import this subpath only when
@@ -32,7 +32,6 @@ function postgresJsStore(connectionString, options = {}) {
32
32
  close: () => sql.end({ timeout: 5 })
33
33
  };
34
34
  }
35
- //#endregion
36
35
  export { postgresJsClient, postgresJsStore };
37
36
 
38
37
  //# sourceMappingURL=postgres-js.mjs.map