@shipfox/api-triggers 2.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 (331) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +224 -0
  5. package/LICENSE +21 -0
  6. package/README.md +300 -0
  7. package/dist/config.d.ts +10 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +42 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/core/compute-next-fire-at.d.ts +9 -0
  12. package/dist/core/compute-next-fire-at.d.ts.map +1 -0
  13. package/dist/core/compute-next-fire-at.js +28 -0
  14. package/dist/core/compute-next-fire-at.js.map +1 -0
  15. package/dist/core/config.d.ts +26 -0
  16. package/dist/core/config.d.ts.map +1 -0
  17. package/dist/core/config.js +68 -0
  18. package/dist/core/config.js.map +1 -0
  19. package/dist/core/dispatch-integration-event.d.ts +14 -0
  20. package/dist/core/dispatch-integration-event.d.ts.map +1 -0
  21. package/dist/core/dispatch-integration-event.js +136 -0
  22. package/dist/core/dispatch-integration-event.js.map +1 -0
  23. package/dist/core/drain-cron-schedules.d.ts +30 -0
  24. package/dist/core/drain-cron-schedules.d.ts.map +1 -0
  25. package/dist/core/drain-cron-schedules.js +76 -0
  26. package/dist/core/drain-cron-schedules.js.map +1 -0
  27. package/dist/core/entities/cron-schedule.d.ts +11 -0
  28. package/dist/core/entities/cron-schedule.d.ts.map +1 -0
  29. package/dist/core/entities/cron-schedule.js +3 -0
  30. package/dist/core/entities/cron-schedule.js.map +1 -0
  31. package/dist/core/entities/decision.d.ts +23 -0
  32. package/dist/core/entities/decision.d.ts.map +1 -0
  33. package/dist/core/entities/decision.js +7 -0
  34. package/dist/core/entities/decision.js.map +1 -0
  35. package/dist/core/entities/index.d.ts +3 -0
  36. package/dist/core/entities/index.d.ts.map +1 -0
  37. package/dist/core/entities/index.js +3 -0
  38. package/dist/core/entities/index.js.map +1 -0
  39. package/dist/core/entities/job-listener-subscription.d.ts +14 -0
  40. package/dist/core/entities/job-listener-subscription.d.ts.map +1 -0
  41. package/dist/core/entities/job-listener-subscription.js +3 -0
  42. package/dist/core/entities/job-listener-subscription.js.map +1 -0
  43. package/dist/core/entities/received-event.d.ts +28 -0
  44. package/dist/core/entities/received-event.d.ts.map +1 -0
  45. package/dist/core/entities/received-event.js +14 -0
  46. package/dist/core/entities/received-event.js.map +1 -0
  47. package/dist/core/entities/subscription.d.ts +13 -0
  48. package/dist/core/entities/subscription.d.ts.map +1 -0
  49. package/dist/core/entities/subscription.js +3 -0
  50. package/dist/core/entities/subscription.js.map +1 -0
  51. package/dist/core/errors.d.ts +25 -0
  52. package/dist/core/errors.d.ts.map +1 -0
  53. package/dist/core/errors.js +41 -0
  54. package/dist/core/errors.js.map +1 -0
  55. package/dist/core/fire-cron.d.ts +28 -0
  56. package/dist/core/fire-cron.d.ts.map +1 -0
  57. package/dist/core/fire-cron.js +85 -0
  58. package/dist/core/fire-cron.js.map +1 -0
  59. package/dist/core/fire-manual.d.ts +9 -0
  60. package/dist/core/fire-manual.d.ts.map +1 -0
  61. package/dist/core/fire-manual.js +87 -0
  62. package/dist/core/fire-manual.js.map +1 -0
  63. package/dist/core/index.d.ts +11 -0
  64. package/dist/core/index.d.ts.map +1 -0
  65. package/dist/core/index.js +10 -0
  66. package/dist/core/index.js.map +1 -0
  67. package/dist/core/record-trigger-history.d.ts +35 -0
  68. package/dist/core/record-trigger-history.d.ts.map +1 -0
  69. package/dist/core/record-trigger-history.js +75 -0
  70. package/dist/core/record-trigger-history.js.map +1 -0
  71. package/dist/core/route-event-to-job-listeners.d.ts +31 -0
  72. package/dist/core/route-event-to-job-listeners.d.ts.map +1 -0
  73. package/dist/core/route-event-to-job-listeners.js +140 -0
  74. package/dist/core/route-event-to-job-listeners.js.map +1 -0
  75. package/dist/db/cron-schedules.d.ts +36 -0
  76. package/dist/db/cron-schedules.d.ts.map +1 -0
  77. package/dist/db/cron-schedules.js +104 -0
  78. package/dist/db/cron-schedules.js.map +1 -0
  79. package/dist/db/db.d.ts +2515 -0
  80. package/dist/db/db.d.ts.map +1 -0
  81. package/dist/db/db.js +28 -0
  82. package/dist/db/db.js.map +1 -0
  83. package/dist/db/event-history.d.ts +50 -0
  84. package/dist/db/event-history.d.ts.map +1 -0
  85. package/dist/db/event-history.js +207 -0
  86. package/dist/db/event-history.js.map +1 -0
  87. package/dist/db/event-queries.d.ts +38 -0
  88. package/dist/db/event-queries.d.ts.map +1 -0
  89. package/dist/db/event-queries.js +78 -0
  90. package/dist/db/event-queries.js.map +1 -0
  91. package/dist/db/index.d.ts +11 -0
  92. package/dist/db/index.d.ts.map +1 -0
  93. package/dist/db/index.js +14 -0
  94. package/dist/db/index.js.map +1 -0
  95. package/dist/db/job-listener-subscriptions.d.ts +24 -0
  96. package/dist/db/job-listener-subscriptions.d.ts.map +1 -0
  97. package/dist/db/job-listener-subscriptions.js +69 -0
  98. package/dist/db/job-listener-subscriptions.js.map +1 -0
  99. package/dist/db/received-events.d.ts +7 -0
  100. package/dist/db/received-events.d.ts.map +1 -0
  101. package/dist/db/received-events.js +11 -0
  102. package/dist/db/received-events.js.map +1 -0
  103. package/dist/db/schema/common.d.ts +2 -0
  104. package/dist/db/schema/common.d.ts.map +1 -0
  105. package/dist/db/schema/common.js +4 -0
  106. package/dist/db/schema/common.js.map +1 -0
  107. package/dist/db/schema/cron-schedules.d.ts +148 -0
  108. package/dist/db/schema/cron-schedules.d.ts.map +1 -0
  109. package/dist/db/schema/cron-schedules.js +39 -0
  110. package/dist/db/schema/cron-schedules.js.map +1 -0
  111. package/dist/db/schema/decisions.d.ts +284 -0
  112. package/dist/db/schema/decisions.d.ts.map +1 -0
  113. package/dist/db/schema/decisions.js +70 -0
  114. package/dist/db/schema/decisions.js.map +1 -0
  115. package/dist/db/schema/job-listener-subscriptions.d.ts +185 -0
  116. package/dist/db/schema/job-listener-subscriptions.d.ts.map +1 -0
  117. package/dist/db/schema/job-listener-subscriptions.js +41 -0
  118. package/dist/db/schema/job-listener-subscriptions.js.map +1 -0
  119. package/dist/db/schema/outbox.d.ts +195 -0
  120. package/dist/db/schema/outbox.d.ts.map +1 -0
  121. package/dist/db/schema/outbox.js +5 -0
  122. package/dist/db/schema/outbox.js.map +1 -0
  123. package/dist/db/schema/received-events.d.ts +544 -0
  124. package/dist/db/schema/received-events.d.ts.map +1 -0
  125. package/dist/db/schema/received-events.js +86 -0
  126. package/dist/db/schema/received-events.js.map +1 -0
  127. package/dist/db/schema/subscriptions.d.ts +182 -0
  128. package/dist/db/schema/subscriptions.d.ts.map +1 -0
  129. package/dist/db/schema/subscriptions.js +39 -0
  130. package/dist/db/schema/subscriptions.js.map +1 -0
  131. package/dist/db/subscriptions.d.ts +26 -0
  132. package/dist/db/subscriptions.d.ts.map +1 -0
  133. package/dist/db/subscriptions.js +103 -0
  134. package/dist/db/subscriptions.js.map +1 -0
  135. package/dist/index.d.ts +7 -0
  136. package/dist/index.d.ts.map +1 -0
  137. package/dist/index.js +68 -0
  138. package/dist/index.js.map +1 -0
  139. package/dist/metrics/index.d.ts +3 -0
  140. package/dist/metrics/index.d.ts.map +1 -0
  141. package/dist/metrics/index.js +4 -0
  142. package/dist/metrics/index.js.map +1 -0
  143. package/dist/metrics/instance.d.ts +15 -0
  144. package/dist/metrics/instance.d.ts.map +1 -0
  145. package/dist/metrics/instance.js +32 -0
  146. package/dist/metrics/instance.js.map +1 -0
  147. package/dist/metrics/service.d.ts +2 -0
  148. package/dist/metrics/service.d.ts.map +1 -0
  149. package/dist/metrics/service.js +15 -0
  150. package/dist/metrics/service.js.map +1 -0
  151. package/dist/presentation/dto/trigger-events.d.ts +7 -0
  152. package/dist/presentation/dto/trigger-events.d.ts.map +1 -0
  153. package/dist/presentation/dto/trigger-events.js +47 -0
  154. package/dist/presentation/dto/trigger-events.js.map +1 -0
  155. package/dist/presentation/index.d.ts +3 -0
  156. package/dist/presentation/index.d.ts.map +1 -0
  157. package/dist/presentation/index.js +4 -0
  158. package/dist/presentation/index.js.map +1 -0
  159. package/dist/presentation/routes/fire-manual.d.ts +2 -0
  160. package/dist/presentation/routes/fire-manual.d.ts.map +1 -0
  161. package/dist/presentation/routes/fire-manual.js +71 -0
  162. package/dist/presentation/routes/fire-manual.js.map +1 -0
  163. package/dist/presentation/routes/get-trigger-event.d.ts +2 -0
  164. package/dist/presentation/routes/get-trigger-event.d.ts.map +1 -0
  165. package/dist/presentation/routes/get-trigger-event.js +37 -0
  166. package/dist/presentation/routes/get-trigger-event.js.map +1 -0
  167. package/dist/presentation/routes/index.d.ts +3 -0
  168. package/dist/presentation/routes/index.d.ts.map +1 -0
  169. package/dist/presentation/routes/index.js +27 -0
  170. package/dist/presentation/routes/index.js.map +1 -0
  171. package/dist/presentation/routes/list-trigger-event-facets.d.ts +2 -0
  172. package/dist/presentation/routes/list-trigger-event-facets.d.ts.map +1 -0
  173. package/dist/presentation/routes/list-trigger-event-facets.js +29 -0
  174. package/dist/presentation/routes/list-trigger-event-facets.js.map +1 -0
  175. package/dist/presentation/routes/list-trigger-events.d.ts +2 -0
  176. package/dist/presentation/routes/list-trigger-events.d.ts.map +1 -0
  177. package/dist/presentation/routes/list-trigger-events.js +56 -0
  178. package/dist/presentation/routes/list-trigger-events.js.map +1 -0
  179. package/dist/presentation/subscribers/index.d.ts +6 -0
  180. package/dist/presentation/subscribers/index.d.ts.map +1 -0
  181. package/dist/presentation/subscribers/index.js +7 -0
  182. package/dist/presentation/subscribers/index.js.map +1 -0
  183. package/dist/presentation/subscribers/on-definition-deleted.d.ts +3 -0
  184. package/dist/presentation/subscribers/on-definition-deleted.d.ts.map +1 -0
  185. package/dist/presentation/subscribers/on-definition-deleted.js +8 -0
  186. package/dist/presentation/subscribers/on-definition-deleted.js.map +1 -0
  187. package/dist/presentation/subscribers/on-definition-resolved.d.ts +3 -0
  188. package/dist/presentation/subscribers/on-definition-resolved.d.ts.map +1 -0
  189. package/dist/presentation/subscribers/on-definition-resolved.js +11 -0
  190. package/dist/presentation/subscribers/on-definition-resolved.js.map +1 -0
  191. package/dist/presentation/subscribers/on-integration-event-received.d.ts +4 -0
  192. package/dist/presentation/subscribers/on-integration-event-received.d.ts.map +1 -0
  193. package/dist/presentation/subscribers/on-integration-event-received.js +17 -0
  194. package/dist/presentation/subscribers/on-integration-event-received.js.map +1 -0
  195. package/dist/presentation/subscribers/on-job-activated.d.ts +3 -0
  196. package/dist/presentation/subscribers/on-job-activated.d.ts.map +1 -0
  197. package/dist/presentation/subscribers/on-job-activated.js +13 -0
  198. package/dist/presentation/subscribers/on-job-activated.js.map +1 -0
  199. package/dist/presentation/subscribers/on-job-terminated.d.ts +3 -0
  200. package/dist/presentation/subscribers/on-job-terminated.d.ts.map +1 -0
  201. package/dist/presentation/subscribers/on-job-terminated.js +6 -0
  202. package/dist/presentation/subscribers/on-job-terminated.js.map +1 -0
  203. package/dist/temporal/activities/drain-cron-batch.d.ts +4 -0
  204. package/dist/temporal/activities/drain-cron-batch.d.ts.map +1 -0
  205. package/dist/temporal/activities/drain-cron-batch.js +20 -0
  206. package/dist/temporal/activities/drain-cron-batch.js.map +1 -0
  207. package/dist/temporal/activities/index.d.ts +10 -0
  208. package/dist/temporal/activities/index.d.ts.map +1 -0
  209. package/dist/temporal/activities/index.js +15 -0
  210. package/dist/temporal/activities/index.js.map +1 -0
  211. package/dist/temporal/activities/prune-trigger-events.d.ts +4 -0
  212. package/dist/temporal/activities/prune-trigger-events.d.ts.map +1 -0
  213. package/dist/temporal/activities/prune-trigger-events.js +11 -0
  214. package/dist/temporal/activities/prune-trigger-events.js.map +1 -0
  215. package/dist/temporal/constants.d.ts +7 -0
  216. package/dist/temporal/constants.d.ts.map +1 -0
  217. package/dist/temporal/constants.js +7 -0
  218. package/dist/temporal/constants.js.map +1 -0
  219. package/dist/temporal/workflows/cron-tick-cron.d.ts +9 -0
  220. package/dist/temporal/workflows/cron-tick-cron.d.ts.map +1 -0
  221. package/dist/temporal/workflows/cron-tick-cron.js +54 -0
  222. package/dist/temporal/workflows/cron-tick-cron.js.map +1 -0
  223. package/dist/temporal/workflows/index.d.ts +3 -0
  224. package/dist/temporal/workflows/index.d.ts.map +1 -0
  225. package/dist/temporal/workflows/index.js +4 -0
  226. package/dist/temporal/workflows/index.js.map +1 -0
  227. package/dist/temporal/workflows/prune-trigger-events-cron.d.ts +2 -0
  228. package/dist/temporal/workflows/prune-trigger-events-cron.d.ts.map +1 -0
  229. package/dist/temporal/workflows/prune-trigger-events-cron.js +18 -0
  230. package/dist/temporal/workflows/prune-trigger-events-cron.js.map +1 -0
  231. package/dist/tsconfig.test.tsbuildinfo +1 -0
  232. package/drizzle/0000_initial.sql +109 -0
  233. package/drizzle/meta/0000_snapshot.json +905 -0
  234. package/drizzle/meta/_journal.json +13 -0
  235. package/drizzle.config.ts +14 -0
  236. package/package.json +83 -0
  237. package/src/config.test.ts +33 -0
  238. package/src/config.ts +53 -0
  239. package/src/core/compute-next-fire-at.test.ts +69 -0
  240. package/src/core/compute-next-fire-at.ts +37 -0
  241. package/src/core/config.test.ts +213 -0
  242. package/src/core/config.ts +86 -0
  243. package/src/core/dispatch-integration-event.history-failure.test.ts +66 -0
  244. package/src/core/dispatch-integration-event.test.ts +1006 -0
  245. package/src/core/dispatch-integration-event.ts +150 -0
  246. package/src/core/drain-cron-schedules.test.ts +265 -0
  247. package/src/core/drain-cron-schedules.ts +90 -0
  248. package/src/core/entities/cron-schedule.ts +10 -0
  249. package/src/core/entities/decision.ts +24 -0
  250. package/src/core/entities/index.ts +5 -0
  251. package/src/core/entities/job-listener-subscription.ts +14 -0
  252. package/src/core/entities/received-event.ts +36 -0
  253. package/src/core/entities/subscription.ts +12 -0
  254. package/src/core/errors.ts +63 -0
  255. package/src/core/fire-cron.test.ts +146 -0
  256. package/src/core/fire-cron.ts +98 -0
  257. package/src/core/fire-manual.test.ts +157 -0
  258. package/src/core/fire-manual.ts +92 -0
  259. package/src/core/index.ts +34 -0
  260. package/src/core/record-trigger-history.test.ts +159 -0
  261. package/src/core/record-trigger-history.ts +145 -0
  262. package/src/core/route-event-to-job-listeners.test.ts +369 -0
  263. package/src/core/route-event-to-job-listeners.ts +184 -0
  264. package/src/db/cron-schedules.test.ts +358 -0
  265. package/src/db/cron-schedules.ts +163 -0
  266. package/src/db/db.ts +31 -0
  267. package/src/db/event-history.test.ts +421 -0
  268. package/src/db/event-history.ts +279 -0
  269. package/src/db/event-queries.ts +140 -0
  270. package/src/db/index.ts +51 -0
  271. package/src/db/job-listener-subscriptions.test.ts +270 -0
  272. package/src/db/job-listener-subscriptions.ts +133 -0
  273. package/src/db/received-events.ts +16 -0
  274. package/src/db/schema/common.ts +3 -0
  275. package/src/db/schema/cron-schedules.ts +37 -0
  276. package/src/db/schema/decisions.test.ts +279 -0
  277. package/src/db/schema/decisions.ts +77 -0
  278. package/src/db/schema/job-listener-subscriptions.ts +65 -0
  279. package/src/db/schema/outbox.ts +4 -0
  280. package/src/db/schema/received-events.test.ts +135 -0
  281. package/src/db/schema/received-events.ts +93 -0
  282. package/src/db/schema/subscriptions.ts +46 -0
  283. package/src/db/subscriptions.test.ts +340 -0
  284. package/src/db/subscriptions.ts +179 -0
  285. package/src/index.ts +108 -0
  286. package/src/metrics/index.ts +8 -0
  287. package/src/metrics/instance.ts +33 -0
  288. package/src/metrics/service.ts +18 -0
  289. package/src/presentation/dto/trigger-events.test.ts +144 -0
  290. package/src/presentation/dto/trigger-events.ts +60 -0
  291. package/src/presentation/index.ts +6 -0
  292. package/src/presentation/routes/fire-manual.test.ts +118 -0
  293. package/src/presentation/routes/fire-manual.ts +70 -0
  294. package/src/presentation/routes/get-trigger-event.test.ts +184 -0
  295. package/src/presentation/routes/get-trigger-event.ts +37 -0
  296. package/src/presentation/routes/index.ts +21 -0
  297. package/src/presentation/routes/list-trigger-event-facets.test.ts +116 -0
  298. package/src/presentation/routes/list-trigger-event-facets.ts +29 -0
  299. package/src/presentation/routes/list-trigger-events.test.ts +379 -0
  300. package/src/presentation/routes/list-trigger-events.ts +68 -0
  301. package/src/presentation/subscribers/index.ts +5 -0
  302. package/src/presentation/subscribers/on-definition-deleted.test.ts +42 -0
  303. package/src/presentation/subscribers/on-definition-deleted.ts +6 -0
  304. package/src/presentation/subscribers/on-definition-resolved.test.ts +67 -0
  305. package/src/presentation/subscribers/on-definition-resolved.ts +11 -0
  306. package/src/presentation/subscribers/on-integration-event-received.test.ts +53 -0
  307. package/src/presentation/subscribers/on-integration-event-received.ts +21 -0
  308. package/src/presentation/subscribers/on-job-activated.ts +14 -0
  309. package/src/presentation/subscribers/on-job-terminated.ts +6 -0
  310. package/src/temporal/activities/drain-cron-batch.ts +20 -0
  311. package/src/temporal/activities/index.ts +15 -0
  312. package/src/temporal/activities/prune-trigger-events.test.ts +78 -0
  313. package/src/temporal/activities/prune-trigger-events.ts +9 -0
  314. package/src/temporal/constants.ts +7 -0
  315. package/src/temporal/workflows/cron-tick-cron.ts +56 -0
  316. package/src/temporal/workflows/index.ts +2 -0
  317. package/src/temporal/workflows/prune-trigger-events-cron.ts +17 -0
  318. package/test/env.ts +8 -0
  319. package/test/factories/cron-schedule.ts +34 -0
  320. package/test/factories/decision.ts +49 -0
  321. package/test/factories/job-listener-subscription.ts +42 -0
  322. package/test/factories/received-event.ts +49 -0
  323. package/test/factories/subscription.ts +38 -0
  324. package/test/globalSetup.ts +20 -0
  325. package/test/index.ts +5 -0
  326. package/test/setup.ts +17 -0
  327. package/tsconfig.build.json +9 -0
  328. package/tsconfig.build.tsbuildinfo +1 -0
  329. package/tsconfig.json +3 -0
  330. package/tsconfig.test.json +8 -0
  331. package/vitest.config.ts +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/compute-next-fire-at.ts"],"sourcesContent":["import {CronExpressionParser} from 'cron-parser';\n\nexport interface ComputeNextFireAtParams {\n readonly cronExpression: string;\n readonly timezone: string;\n readonly from: Date;\n readonly subscriptionId: string;\n readonly jitterWindowSeconds: number;\n}\n\nexport function computeNextFireAt(params: ComputeNextFireAtParams): Date {\n const iterator = CronExpressionParser.parse(params.cronExpression, {\n currentDate: params.from,\n tz: params.timezone,\n });\n const occurrence = iterator.next().toDate();\n const following = iterator.next().toDate();\n const gapMs = following.getTime() - occurrence.getTime();\n const offsetMs = jitterOffsetMs(params.subscriptionId, params.jitterWindowSeconds, gapMs);\n return new Date(occurrence.getTime() + offsetMs);\n}\n\nfunction jitterOffsetMs(subscriptionId: string, windowSeconds: number, gapMs: number): number {\n const windowMs = Math.floor(windowSeconds * 1000);\n const clampMs = Math.min(windowMs, gapMs);\n if (clampMs <= 0) return 0;\n return hashStringToUint32(subscriptionId) % clampMs;\n}\n\nfunction hashStringToUint32(value: string): number {\n let hash = 0x811c9dc5;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n return hash >>> 0;\n}\n"],"names":["CronExpressionParser","computeNextFireAt","params","iterator","parse","cronExpression","currentDate","from","tz","timezone","occurrence","next","toDate","following","gapMs","getTime","offsetMs","jitterOffsetMs","subscriptionId","jitterWindowSeconds","Date","windowSeconds","windowMs","Math","floor","clampMs","min","hashStringToUint32","value","hash","index","length","charCodeAt","imul"],"mappings":"AAAA,SAAQA,oBAAoB,QAAO,cAAc;AAUjD,OAAO,SAASC,kBAAkBC,MAA+B;IAC/D,MAAMC,WAAWH,qBAAqBI,KAAK,CAACF,OAAOG,cAAc,EAAE;QACjEC,aAAaJ,OAAOK,IAAI;QACxBC,IAAIN,OAAOO,QAAQ;IACrB;IACA,MAAMC,aAAaP,SAASQ,IAAI,GAAGC,MAAM;IACzC,MAAMC,YAAYV,SAASQ,IAAI,GAAGC,MAAM;IACxC,MAAME,QAAQD,UAAUE,OAAO,KAAKL,WAAWK,OAAO;IACtD,MAAMC,WAAWC,eAAef,OAAOgB,cAAc,EAAEhB,OAAOiB,mBAAmB,EAAEL;IACnF,OAAO,IAAIM,KAAKV,WAAWK,OAAO,KAAKC;AACzC;AAEA,SAASC,eAAeC,cAAsB,EAAEG,aAAqB,EAAEP,KAAa;IAClF,MAAMQ,WAAWC,KAAKC,KAAK,CAACH,gBAAgB;IAC5C,MAAMI,UAAUF,KAAKG,GAAG,CAACJ,UAAUR;IACnC,IAAIW,WAAW,GAAG,OAAO;IACzB,OAAOE,mBAAmBT,kBAAkBO;AAC9C;AAEA,SAASE,mBAAmBC,KAAa;IACvC,IAAIC,OAAO;IACX,IAAK,IAAIC,QAAQ,GAAGA,QAAQF,MAAMG,MAAM,EAAED,SAAS,EAAG;QACpDD,QAAQD,MAAMI,UAAU,CAACF;QACzBD,OAAON,KAAKU,IAAI,CAACJ,MAAM;IACzB;IACA,OAAOA,SAAS;AAClB"}
@@ -0,0 +1,26 @@
1
+ import type { TriggerSubscription } from './entities/subscription.js';
2
+ export declare function readConfigInputs(subscription: TriggerSubscription): Record<string, unknown> | undefined;
3
+ export type TriggerFilterEvaluation = {
4
+ kind: 'matched';
5
+ } | {
6
+ kind: 'filtered';
7
+ } | {
8
+ kind: 'filter-error';
9
+ reason: string;
10
+ };
11
+ export type StoredFilterEvaluation = TriggerFilterEvaluation;
12
+ export interface EvaluateStoredFilterParams {
13
+ value: unknown;
14
+ context: Record<string, unknown>;
15
+ invalidReason: string;
16
+ evaluationFailedReason: string;
17
+ }
18
+ export declare function evaluateStoredFilter(params: EvaluateStoredFilterParams): StoredFilterEvaluation;
19
+ export interface EvaluateTriggerFilterParams {
20
+ subscription: TriggerSubscription;
21
+ source: string;
22
+ event: string;
23
+ payload: unknown;
24
+ }
25
+ export declare function evaluateTriggerFilter(params: EvaluateTriggerFilterParams): TriggerFilterEvaluation;
26
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAKpE,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,mBAAmB,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKrC;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,UAAU,CAAA;CAAC,GAClB;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAE3C,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,sBAAsB,CAwB/F;AAED,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,mBAAmB,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,2BAA2B,GAClC,uBAAuB,CAUzB"}
@@ -0,0 +1,68 @@
1
+ import { createWorkflowExpression, evaluateWorkflowPredicateFailClosed, InvalidWorkflowExpressionError } from '@shipfox/expression';
2
+ // Narrow the jsonb projection at the read boundary: the parser writes the right shapes,
3
+ // but the column is unconstrained and these values reach run inputs.
4
+ export function readConfigInputs(subscription) {
5
+ const value = subscription.config.with;
6
+ if (value === null || value === undefined) return undefined;
7
+ if (typeof value !== 'object' || Array.isArray(value)) return undefined;
8
+ return value;
9
+ }
10
+ export function evaluateStoredFilter(params) {
11
+ const { value } = params;
12
+ if (value === null || value === undefined) return {
13
+ kind: 'matched'
14
+ };
15
+ if (typeof value !== 'string' || value.trim() === '') {
16
+ return {
17
+ kind: 'filter-error',
18
+ reason: params.invalidReason
19
+ };
20
+ }
21
+ let expression;
22
+ try {
23
+ expression = createWorkflowExpression({
24
+ source: value,
25
+ check: {
26
+ mode: 'syntax'
27
+ }
28
+ });
29
+ } catch (error) {
30
+ return {
31
+ kind: 'filter-error',
32
+ reason: reasonFrom(error)
33
+ };
34
+ }
35
+ const result = evaluateWorkflowPredicateFailClosed(expression, params.context);
36
+ if (result.evaluationFailed) {
37
+ return {
38
+ kind: 'filter-error',
39
+ reason: params.evaluationFailedReason
40
+ };
41
+ }
42
+ return result.value ? {
43
+ kind: 'matched'
44
+ } : {
45
+ kind: 'filtered'
46
+ };
47
+ }
48
+ export function evaluateTriggerFilter(params) {
49
+ return evaluateStoredFilter({
50
+ value: params.subscription.config.filter,
51
+ context: {
52
+ event: params.payload,
53
+ trigger: {
54
+ source: params.source,
55
+ event: params.event
56
+ }
57
+ },
58
+ invalidReason: 'Trigger subscription filter must be a non-empty string when set',
59
+ evaluationFailedReason: 'Trigger filter evaluation failed'
60
+ });
61
+ }
62
+ function reasonFrom(error) {
63
+ if (error instanceof InvalidWorkflowExpressionError) return error.reason;
64
+ if (error instanceof Error) return error.message;
65
+ return String(error);
66
+ }
67
+
68
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/config.ts"],"sourcesContent":["import {\n createWorkflowExpression,\n evaluateWorkflowPredicateFailClosed,\n InvalidWorkflowExpressionError,\n type WorkflowExpression,\n} from '@shipfox/expression';\nimport type {TriggerSubscription} from './entities/subscription.js';\n\n// Narrow the jsonb projection at the read boundary: the parser writes the right shapes,\n// but the column is unconstrained and these values reach run inputs.\n\nexport function readConfigInputs(\n subscription: TriggerSubscription,\n): Record<string, unknown> | undefined {\n const value = subscription.config.with;\n if (value === null || value === undefined) return undefined;\n if (typeof value !== 'object' || Array.isArray(value)) return undefined;\n return value as Record<string, unknown>;\n}\n\nexport type TriggerFilterEvaluation =\n | {kind: 'matched'}\n | {kind: 'filtered'}\n | {kind: 'filter-error'; reason: string};\n\nexport type StoredFilterEvaluation = TriggerFilterEvaluation;\n\nexport interface EvaluateStoredFilterParams {\n value: unknown;\n context: Record<string, unknown>;\n invalidReason: string;\n evaluationFailedReason: string;\n}\n\nexport function evaluateStoredFilter(params: EvaluateStoredFilterParams): StoredFilterEvaluation {\n const {value} = params;\n if (value === null || value === undefined) return {kind: 'matched'};\n if (typeof value !== 'string' || value.trim() === '') {\n return {\n kind: 'filter-error',\n reason: params.invalidReason,\n };\n }\n\n let expression: WorkflowExpression;\n try {\n expression = createWorkflowExpression({source: value, check: {mode: 'syntax'}});\n } catch (error) {\n return {kind: 'filter-error', reason: reasonFrom(error)};\n }\n\n const result = evaluateWorkflowPredicateFailClosed(expression, params.context);\n\n if (result.evaluationFailed) {\n return {kind: 'filter-error', reason: params.evaluationFailedReason};\n }\n\n return result.value ? {kind: 'matched'} : {kind: 'filtered'};\n}\n\nexport interface EvaluateTriggerFilterParams {\n subscription: TriggerSubscription;\n source: string;\n event: string;\n payload: unknown;\n}\n\nexport function evaluateTriggerFilter(\n params: EvaluateTriggerFilterParams,\n): TriggerFilterEvaluation {\n return evaluateStoredFilter({\n value: params.subscription.config.filter,\n context: {\n event: params.payload,\n trigger: {source: params.source, event: params.event},\n },\n invalidReason: 'Trigger subscription filter must be a non-empty string when set',\n evaluationFailedReason: 'Trigger filter evaluation failed',\n });\n}\n\nfunction reasonFrom(error: unknown): string {\n if (error instanceof InvalidWorkflowExpressionError) return error.reason;\n if (error instanceof Error) return error.message;\n return String(error);\n}\n"],"names":["createWorkflowExpression","evaluateWorkflowPredicateFailClosed","InvalidWorkflowExpressionError","readConfigInputs","subscription","value","config","with","undefined","Array","isArray","evaluateStoredFilter","params","kind","trim","reason","invalidReason","expression","source","check","mode","error","reasonFrom","result","context","evaluationFailed","evaluationFailedReason","evaluateTriggerFilter","filter","event","payload","trigger","Error","message","String"],"mappings":"AAAA,SACEA,wBAAwB,EACxBC,mCAAmC,EACnCC,8BAA8B,QAEzB,sBAAsB;AAG7B,wFAAwF;AACxF,qEAAqE;AAErE,OAAO,SAASC,iBACdC,YAAiC;IAEjC,MAAMC,QAAQD,aAAaE,MAAM,CAACC,IAAI;IACtC,IAAIF,UAAU,QAAQA,UAAUG,WAAW,OAAOA;IAClD,IAAI,OAAOH,UAAU,YAAYI,MAAMC,OAAO,CAACL,QAAQ,OAAOG;IAC9D,OAAOH;AACT;AAgBA,OAAO,SAASM,qBAAqBC,MAAkC;IACrE,MAAM,EAACP,KAAK,EAAC,GAAGO;IAChB,IAAIP,UAAU,QAAQA,UAAUG,WAAW,OAAO;QAACK,MAAM;IAAS;IAClE,IAAI,OAAOR,UAAU,YAAYA,MAAMS,IAAI,OAAO,IAAI;QACpD,OAAO;YACLD,MAAM;YACNE,QAAQH,OAAOI,aAAa;QAC9B;IACF;IAEA,IAAIC;IACJ,IAAI;QACFA,aAAajB,yBAAyB;YAACkB,QAAQb;YAAOc,OAAO;gBAACC,MAAM;YAAQ;QAAC;IAC/E,EAAE,OAAOC,OAAO;QACd,OAAO;YAACR,MAAM;YAAgBE,QAAQO,WAAWD;QAAM;IACzD;IAEA,MAAME,SAAStB,oCAAoCgB,YAAYL,OAAOY,OAAO;IAE7E,IAAID,OAAOE,gBAAgB,EAAE;QAC3B,OAAO;YAACZ,MAAM;YAAgBE,QAAQH,OAAOc,sBAAsB;QAAA;IACrE;IAEA,OAAOH,OAAOlB,KAAK,GAAG;QAACQ,MAAM;IAAS,IAAI;QAACA,MAAM;IAAU;AAC7D;AASA,OAAO,SAASc,sBACdf,MAAmC;IAEnC,OAAOD,qBAAqB;QAC1BN,OAAOO,OAAOR,YAAY,CAACE,MAAM,CAACsB,MAAM;QACxCJ,SAAS;YACPK,OAAOjB,OAAOkB,OAAO;YACrBC,SAAS;gBAACb,QAAQN,OAAOM,MAAM;gBAAEW,OAAOjB,OAAOiB,KAAK;YAAA;QACtD;QACAb,eAAe;QACfU,wBAAwB;IAC1B;AACF;AAEA,SAASJ,WAAWD,KAAc;IAChC,IAAIA,iBAAiBnB,gCAAgC,OAAOmB,MAAMN,MAAM;IACxE,IAAIM,iBAAiBW,OAAO,OAAOX,MAAMY,OAAO;IAChD,OAAOC,OAAOb;AAChB"}
@@ -0,0 +1,14 @@
1
+ export interface DispatchIntegrationEventParams {
2
+ eventRef: string;
3
+ workspaceId: string;
4
+ provider: string;
5
+ source: string;
6
+ event: string;
7
+ deliveryId: string;
8
+ connectionId: string;
9
+ connectionName: string | null;
10
+ payload: unknown;
11
+ receivedAt: Date;
12
+ }
13
+ export declare function dispatchIntegrationEvent(params: DispatchIntegrationEventParams): Promise<void>;
14
+ //# sourceMappingURL=dispatch-integration-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-integration-event.d.ts","sourceRoot":"","sources":["../../src/core/dispatch-integration-event.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB;AAcD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,IAAI,CAAC,CA+Gf"}
@@ -0,0 +1,136 @@
1
+ import { isPermanentRunWorkflowError, runWorkflow } from '@shipfox/api-workflows';
2
+ import { findMatchingSubscriptions } from '#db/subscriptions.js';
3
+ import { eventOutcomeCount, eventReceivedCount, subscriptionTriggeredCount } from '#metrics/instance.js';
4
+ import { evaluateTriggerFilter, readConfigInputs } from './config.js';
5
+ import { beginTriggerHistory, toReason } from './record-trigger-history.js';
6
+ import { routeEventToJobListeners } from './route-event-to-job-listeners.js';
7
+ // Source-agnostic dispatcher: any inbound integration event fans out to every
8
+ // workspace subscription registered for its (source, event) and to every listening
9
+ // job subscribed to it, passing the raw payload through untouched. The module knows
10
+ // nothing about github, gitlab, etc.
11
+ //
12
+ // Continue-on-error: every matched subscription and listener is attempted so one broken
13
+ // subscription cannot starve its siblings. A permanent failure (deleted definition, project
14
+ // mismatch) is recorded and skipped; a transient one is recorded and re-thrown so the outbox
15
+ // replays the whole event and converges (succeeded siblings dedup on the idempotency key). The
16
+ // event reaches a terminal outcome only when no transient error remains: `routed` if any run
17
+ // was created or any listening job matched, `discarded` if nothing matched, otherwise `errored`.
18
+ // History is best-effort; the thrown transient error, not the recorded outcome, drives the retry.
19
+ export async function dispatchIntegrationEvent(params) {
20
+ eventReceivedCount.add(1, {
21
+ provider: params.provider
22
+ });
23
+ const history = await beginTriggerHistory({
24
+ eventRef: params.eventRef,
25
+ origin: 'integration',
26
+ workspaceId: params.workspaceId,
27
+ provider: params.provider,
28
+ source: params.source,
29
+ event: params.event,
30
+ deliveryId: params.deliveryId,
31
+ connectionId: params.connectionId,
32
+ connectionName: params.connectionName,
33
+ payload: params.payload ?? null,
34
+ receivedAt: params.receivedAt
35
+ });
36
+ const subscriptions = await findMatchingSubscriptions({
37
+ workspaceId: params.workspaceId,
38
+ source: params.source,
39
+ event: params.event
40
+ });
41
+ let triggeredCount = 0;
42
+ let triggerEngagedCount = 0;
43
+ let sawTransientError = false;
44
+ let firstTransientError;
45
+ for (const subscription of subscriptions){
46
+ const filterResult = evaluateTriggerFilter({
47
+ subscription,
48
+ source: params.source,
49
+ event: params.event,
50
+ payload: params.payload
51
+ });
52
+ if (filterResult.kind === 'filtered') continue;
53
+ if (filterResult.kind === 'filter-error') {
54
+ triggerEngagedCount += 1;
55
+ await history.filterErrored(subscription, filterResult.reason);
56
+ continue;
57
+ }
58
+ triggerEngagedCount += 1;
59
+ try {
60
+ const run = await runWorkflow({
61
+ workspaceId: subscription.workspaceId,
62
+ projectId: subscription.projectId,
63
+ definitionId: subscription.workflowDefinitionId,
64
+ triggerPayload: {
65
+ provider: params.provider,
66
+ source: params.source,
67
+ event: params.event,
68
+ deliveryId: params.deliveryId,
69
+ data: params.payload
70
+ },
71
+ inputs: readConfigInputs(subscription),
72
+ triggerIdempotencyKey: `${subscription.id}:${params.eventRef}`
73
+ });
74
+ await history.triggered(subscription, run);
75
+ triggeredCount += 1;
76
+ subscriptionTriggeredCount.add(1, {
77
+ provider: params.provider
78
+ });
79
+ } catch (error) {
80
+ await history.dispatchErrored(subscription, toReason(error));
81
+ // Track presence with a flag, not `firstTransientError === undefined`: a thrown
82
+ // value of `undefined` is still a transient failure and must drive the replay.
83
+ if (!isPermanentRunWorkflowError(error) && !sawTransientError) {
84
+ sawTransientError = true;
85
+ firstTransientError = error;
86
+ }
87
+ }
88
+ }
89
+ const listenerResult = await routeEventToJobListeners({
90
+ history,
91
+ eventRef: params.eventRef,
92
+ workspaceId: params.workspaceId,
93
+ provider: params.provider,
94
+ source: params.source,
95
+ event: params.event,
96
+ deliveryId: params.deliveryId,
97
+ payload: params.payload,
98
+ receivedAt: params.receivedAt
99
+ });
100
+ if (listenerResult.transientErrored && !sawTransientError) {
101
+ sawTransientError = true;
102
+ firstTransientError = listenerResult.transientError;
103
+ }
104
+ const totalMatchedCount = triggerEngagedCount + listenerResult.engagedCount;
105
+ if (sawTransientError) {
106
+ eventOutcomeCount.add(1, {
107
+ provider: params.provider,
108
+ outcome: 'failed'
109
+ });
110
+ await history.failed(totalMatchedCount);
111
+ throw firstTransientError;
112
+ }
113
+ if (triggeredCount > 0 || listenerResult.acceptedJobCount > 0) {
114
+ eventOutcomeCount.add(1, {
115
+ provider: params.provider,
116
+ outcome: 'routed'
117
+ });
118
+ await history.routed(totalMatchedCount);
119
+ return;
120
+ }
121
+ if (totalMatchedCount === 0) {
122
+ eventOutcomeCount.add(1, {
123
+ provider: params.provider,
124
+ outcome: 'discarded'
125
+ });
126
+ await history.discarded();
127
+ return;
128
+ }
129
+ eventOutcomeCount.add(1, {
130
+ provider: params.provider,
131
+ outcome: 'errored'
132
+ });
133
+ await history.allErrored(totalMatchedCount);
134
+ }
135
+
136
+ //# sourceMappingURL=dispatch-integration-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/dispatch-integration-event.ts"],"sourcesContent":["import {isPermanentRunWorkflowError, runWorkflow} from '@shipfox/api-workflows';\nimport {findMatchingSubscriptions} from '#db/subscriptions.js';\nimport {\n eventOutcomeCount,\n eventReceivedCount,\n subscriptionTriggeredCount,\n} from '#metrics/instance.js';\nimport {evaluateTriggerFilter, readConfigInputs} from './config.js';\nimport {beginTriggerHistory, toReason} from './record-trigger-history.js';\nimport {routeEventToJobListeners} from './route-event-to-job-listeners.js';\n\nexport interface DispatchIntegrationEventParams {\n eventRef: string;\n workspaceId: string;\n provider: string;\n source: string;\n event: string;\n deliveryId: string;\n connectionId: string;\n connectionName: string | null;\n payload: unknown;\n receivedAt: Date;\n}\n\n// Source-agnostic dispatcher: any inbound integration event fans out to every\n// workspace subscription registered for its (source, event) and to every listening\n// job subscribed to it, passing the raw payload through untouched. The module knows\n// nothing about github, gitlab, etc.\n//\n// Continue-on-error: every matched subscription and listener is attempted so one broken\n// subscription cannot starve its siblings. A permanent failure (deleted definition, project\n// mismatch) is recorded and skipped; a transient one is recorded and re-thrown so the outbox\n// replays the whole event and converges (succeeded siblings dedup on the idempotency key). The\n// event reaches a terminal outcome only when no transient error remains: `routed` if any run\n// was created or any listening job matched, `discarded` if nothing matched, otherwise `errored`.\n// History is best-effort; the thrown transient error, not the recorded outcome, drives the retry.\nexport async function dispatchIntegrationEvent(\n params: DispatchIntegrationEventParams,\n): Promise<void> {\n eventReceivedCount.add(1, {provider: params.provider});\n\n const history = await beginTriggerHistory({\n eventRef: params.eventRef,\n origin: 'integration',\n workspaceId: params.workspaceId,\n provider: params.provider,\n source: params.source,\n event: params.event,\n deliveryId: params.deliveryId,\n connectionId: params.connectionId,\n connectionName: params.connectionName,\n payload: (params.payload ?? null) as Record<string, unknown> | null,\n receivedAt: params.receivedAt,\n });\n\n const subscriptions = await findMatchingSubscriptions({\n workspaceId: params.workspaceId,\n source: params.source,\n event: params.event,\n });\n\n let triggeredCount = 0;\n let triggerEngagedCount = 0;\n let sawTransientError = false;\n let firstTransientError: unknown;\n\n for (const subscription of subscriptions) {\n const filterResult = evaluateTriggerFilter({\n subscription,\n source: params.source,\n event: params.event,\n payload: params.payload,\n });\n if (filterResult.kind === 'filtered') continue;\n if (filterResult.kind === 'filter-error') {\n triggerEngagedCount += 1;\n await history.filterErrored(subscription, filterResult.reason);\n continue;\n }\n triggerEngagedCount += 1;\n\n try {\n const run = await runWorkflow({\n workspaceId: subscription.workspaceId,\n projectId: subscription.projectId,\n definitionId: subscription.workflowDefinitionId,\n triggerPayload: {\n provider: params.provider,\n source: params.source,\n event: params.event,\n deliveryId: params.deliveryId,\n data: params.payload,\n },\n inputs: readConfigInputs(subscription),\n triggerIdempotencyKey: `${subscription.id}:${params.eventRef}`,\n });\n await history.triggered(subscription, run);\n triggeredCount += 1;\n subscriptionTriggeredCount.add(1, {provider: params.provider});\n } catch (error) {\n await history.dispatchErrored(subscription, toReason(error));\n // Track presence with a flag, not `firstTransientError === undefined`: a thrown\n // value of `undefined` is still a transient failure and must drive the replay.\n if (!isPermanentRunWorkflowError(error) && !sawTransientError) {\n sawTransientError = true;\n firstTransientError = error;\n }\n }\n }\n\n const listenerResult = await routeEventToJobListeners({\n history,\n eventRef: params.eventRef,\n workspaceId: params.workspaceId,\n provider: params.provider,\n source: params.source,\n event: params.event,\n deliveryId: params.deliveryId,\n payload: params.payload,\n receivedAt: params.receivedAt,\n });\n\n if (listenerResult.transientErrored && !sawTransientError) {\n sawTransientError = true;\n firstTransientError = listenerResult.transientError;\n }\n\n const totalMatchedCount = triggerEngagedCount + listenerResult.engagedCount;\n\n if (sawTransientError) {\n eventOutcomeCount.add(1, {provider: params.provider, outcome: 'failed'});\n await history.failed(totalMatchedCount);\n throw firstTransientError;\n }\n\n if (triggeredCount > 0 || listenerResult.acceptedJobCount > 0) {\n eventOutcomeCount.add(1, {provider: params.provider, outcome: 'routed'});\n await history.routed(totalMatchedCount);\n return;\n }\n\n if (totalMatchedCount === 0) {\n eventOutcomeCount.add(1, {provider: params.provider, outcome: 'discarded'});\n await history.discarded();\n return;\n }\n\n eventOutcomeCount.add(1, {provider: params.provider, outcome: 'errored'});\n await history.allErrored(totalMatchedCount);\n}\n"],"names":["isPermanentRunWorkflowError","runWorkflow","findMatchingSubscriptions","eventOutcomeCount","eventReceivedCount","subscriptionTriggeredCount","evaluateTriggerFilter","readConfigInputs","beginTriggerHistory","toReason","routeEventToJobListeners","dispatchIntegrationEvent","params","add","provider","history","eventRef","origin","workspaceId","source","event","deliveryId","connectionId","connectionName","payload","receivedAt","subscriptions","triggeredCount","triggerEngagedCount","sawTransientError","firstTransientError","subscription","filterResult","kind","filterErrored","reason","run","projectId","definitionId","workflowDefinitionId","triggerPayload","data","inputs","triggerIdempotencyKey","id","triggered","error","dispatchErrored","listenerResult","transientErrored","transientError","totalMatchedCount","engagedCount","outcome","failed","acceptedJobCount","routed","discarded","allErrored"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export interface DrainDueCronSchedulesParams {
2
+ readonly batchSize: number;
3
+ readonly jitterWindowSeconds: number;
4
+ /**
5
+ * Liveness signal invoked once per processed schedule (e.g. the Temporal activity
6
+ * heartbeat), so a batch stuck on a slow `runWorkflow` is visible rather than
7
+ * looking hung until the start-to-close timeout fires.
8
+ */
9
+ readonly onScheduleProcessed?: (() => void) | undefined;
10
+ }
11
+ export interface CronDrainSummary {
12
+ readonly claimed: number;
13
+ readonly fired: number;
14
+ readonly errored: number;
15
+ readonly retried: number;
16
+ }
17
+ /**
18
+ * Claims one bounded batch of due cron schedules and, per row, advances the schedule
19
+ * and fires the workflow. There is no internal drain loop, so the per-activity ceiling
20
+ * stays a hard `batchSize`.
21
+ *
22
+ * The batch is claimed and processed inside a single transaction, so its `FOR UPDATE
23
+ * SKIP LOCKED` locks are held until commit and concurrent activities/pods claim disjoint
24
+ * rows. Each row runs in a nested savepoint that advances `next_fire_at` before firing:
25
+ * on a transient failure the savepoint rolls back only that row's advance, leaving it due
26
+ * for retry, without blocking the rest of the batch. Firing before the advance commits
27
+ * makes a crash between the two re-fire the (idempotent) occurrence rather than skip it.
28
+ */
29
+ export declare function drainDueCronSchedules(params: DrainDueCronSchedulesParams): Promise<CronDrainSummary>;
30
+ //# sourceMappingURL=drain-cron-schedules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drain-cron-schedules.d.ts","sourceRoot":"","sources":["../../src/core/drain-cron-schedules.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAmD3B"}
@@ -0,0 +1,76 @@
1
+ import { logger } from '@shipfox/node-opentelemetry';
2
+ import { advanceCronSchedule, claimDueCronSchedules, selectDbNow } from '#db/cron-schedules.js';
3
+ import { db } from '#db/db.js';
4
+ import { computeNextFireAt } from './compute-next-fire-at.js';
5
+ import { fireCronSubscription } from './fire-cron.js';
6
+ /**
7
+ * Claims one bounded batch of due cron schedules and, per row, advances the schedule
8
+ * and fires the workflow. There is no internal drain loop, so the per-activity ceiling
9
+ * stays a hard `batchSize`.
10
+ *
11
+ * The batch is claimed and processed inside a single transaction, so its `FOR UPDATE
12
+ * SKIP LOCKED` locks are held until commit and concurrent activities/pods claim disjoint
13
+ * rows. Each row runs in a nested savepoint that advances `next_fire_at` before firing:
14
+ * on a transient failure the savepoint rolls back only that row's advance, leaving it due
15
+ * for retry, without blocking the rest of the batch. Firing before the advance commits
16
+ * makes a crash between the two re-fire the (idempotent) occurrence rather than skip it.
17
+ */ export async function drainDueCronSchedules(params) {
18
+ let claimed = 0;
19
+ let fired = 0;
20
+ let errored = 0;
21
+ let retried = 0;
22
+ await db().transaction(async (tx)=>{
23
+ // One database-clock reading shared by the due check and every advance, so the two
24
+ // never disagree under application/database clock skew.
25
+ const now = await selectDbNow(tx);
26
+ const due = await claimDueCronSchedules({
27
+ tx,
28
+ limit: params.batchSize,
29
+ now
30
+ });
31
+ claimed = due.length;
32
+ for (const schedule of due){
33
+ const scheduledSlot = schedule.nextFireAt;
34
+ try {
35
+ const result = await tx.transaction(async (rowTx)=>{
36
+ const nextFireAt = computeNextFireAt({
37
+ cronExpression: schedule.cronExpression,
38
+ timezone: schedule.timezone,
39
+ from: now,
40
+ subscriptionId: schedule.subscriptionId,
41
+ jitterWindowSeconds: params.jitterWindowSeconds
42
+ });
43
+ await advanceCronSchedule({
44
+ tx: rowTx,
45
+ subscriptionId: schedule.subscriptionId,
46
+ nextFireAt,
47
+ lastFiredAt: scheduledSlot
48
+ });
49
+ return await fireCronSubscription({
50
+ subscriptionId: schedule.subscriptionId,
51
+ scheduledSlot
52
+ });
53
+ });
54
+ if (result.outcome === 'fired') fired += 1;
55
+ else errored += 1;
56
+ } catch (error) {
57
+ // Transient failure: the savepoint rolled back the advance, so the schedule
58
+ // stays due and the next tick (or an activity retry) re-claims it.
59
+ retried += 1;
60
+ logger().warn({
61
+ err: error,
62
+ subscriptionId: schedule.subscriptionId
63
+ }, 'cron drain: transient fire failure; schedule left due for retry');
64
+ }
65
+ params.onScheduleProcessed?.();
66
+ }
67
+ });
68
+ return {
69
+ claimed,
70
+ fired,
71
+ errored,
72
+ retried
73
+ };
74
+ }
75
+
76
+ //# sourceMappingURL=drain-cron-schedules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/drain-cron-schedules.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport {advanceCronSchedule, claimDueCronSchedules, selectDbNow} from '#db/cron-schedules.js';\nimport {db} from '#db/db.js';\nimport {computeNextFireAt} from './compute-next-fire-at.js';\nimport {fireCronSubscription} from './fire-cron.js';\n\nexport interface DrainDueCronSchedulesParams {\n readonly batchSize: number;\n readonly jitterWindowSeconds: number;\n /**\n * Liveness signal invoked once per processed schedule (e.g. the Temporal activity\n * heartbeat), so a batch stuck on a slow `runWorkflow` is visible rather than\n * looking hung until the start-to-close timeout fires.\n */\n readonly onScheduleProcessed?: (() => void) | undefined;\n}\n\nexport interface CronDrainSummary {\n readonly claimed: number;\n readonly fired: number;\n readonly errored: number;\n readonly retried: number;\n}\n\n/**\n * Claims one bounded batch of due cron schedules and, per row, advances the schedule\n * and fires the workflow. There is no internal drain loop, so the per-activity ceiling\n * stays a hard `batchSize`.\n *\n * The batch is claimed and processed inside a single transaction, so its `FOR UPDATE\n * SKIP LOCKED` locks are held until commit and concurrent activities/pods claim disjoint\n * rows. Each row runs in a nested savepoint that advances `next_fire_at` before firing:\n * on a transient failure the savepoint rolls back only that row's advance, leaving it due\n * for retry, without blocking the rest of the batch. Firing before the advance commits\n * makes a crash between the two re-fire the (idempotent) occurrence rather than skip it.\n */\nexport async function drainDueCronSchedules(\n params: DrainDueCronSchedulesParams,\n): Promise<CronDrainSummary> {\n let claimed = 0;\n let fired = 0;\n let errored = 0;\n let retried = 0;\n\n await db().transaction(async (tx) => {\n // One database-clock reading shared by the due check and every advance, so the two\n // never disagree under application/database clock skew.\n const now = await selectDbNow(tx);\n const due = await claimDueCronSchedules({tx, limit: params.batchSize, now});\n claimed = due.length;\n\n for (const schedule of due) {\n const scheduledSlot = schedule.nextFireAt;\n try {\n const result = await tx.transaction(async (rowTx) => {\n const nextFireAt = computeNextFireAt({\n cronExpression: schedule.cronExpression,\n timezone: schedule.timezone,\n from: now,\n subscriptionId: schedule.subscriptionId,\n jitterWindowSeconds: params.jitterWindowSeconds,\n });\n await advanceCronSchedule({\n tx: rowTx,\n subscriptionId: schedule.subscriptionId,\n nextFireAt,\n lastFiredAt: scheduledSlot,\n });\n return await fireCronSubscription({\n subscriptionId: schedule.subscriptionId,\n scheduledSlot,\n });\n });\n if (result.outcome === 'fired') fired += 1;\n else errored += 1;\n } catch (error) {\n // Transient failure: the savepoint rolled back the advance, so the schedule\n // stays due and the next tick (or an activity retry) re-claims it.\n retried += 1;\n logger().warn(\n {err: error, subscriptionId: schedule.subscriptionId},\n 'cron drain: transient fire failure; schedule left due for retry',\n );\n }\n params.onScheduleProcessed?.();\n }\n });\n\n return {claimed, fired, errored, retried};\n}\n"],"names":["logger","advanceCronSchedule","claimDueCronSchedules","selectDbNow","db","computeNextFireAt","fireCronSubscription","drainDueCronSchedules","params","claimed","fired","errored","retried","transaction","tx","now","due","limit","batchSize","length","schedule","scheduledSlot","nextFireAt","result","rowTx","cronExpression","timezone","from","subscriptionId","jitterWindowSeconds","lastFiredAt","outcome","error","warn","err","onScheduleProcessed"],"mappings":"AAAA,SAAQA,MAAM,QAAO,8BAA8B;AACnD,SAAQC,mBAAmB,EAAEC,qBAAqB,EAAEC,WAAW,QAAO,wBAAwB;AAC9F,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,iBAAiB,QAAO,4BAA4B;AAC5D,SAAQC,oBAAoB,QAAO,iBAAiB;AAoBpD;;;;;;;;;;;CAWC,GACD,OAAO,eAAeC,sBACpBC,MAAmC;IAEnC,IAAIC,UAAU;IACd,IAAIC,QAAQ;IACZ,IAAIC,UAAU;IACd,IAAIC,UAAU;IAEd,MAAMR,KAAKS,WAAW,CAAC,OAAOC;QAC5B,mFAAmF;QACnF,wDAAwD;QACxD,MAAMC,MAAM,MAAMZ,YAAYW;QAC9B,MAAME,MAAM,MAAMd,sBAAsB;YAACY;YAAIG,OAAOT,OAAOU,SAAS;YAAEH;QAAG;QACzEN,UAAUO,IAAIG,MAAM;QAEpB,KAAK,MAAMC,YAAYJ,IAAK;YAC1B,MAAMK,gBAAgBD,SAASE,UAAU;YACzC,IAAI;gBACF,MAAMC,SAAS,MAAMT,GAAGD,WAAW,CAAC,OAAOW;oBACzC,MAAMF,aAAajB,kBAAkB;wBACnCoB,gBAAgBL,SAASK,cAAc;wBACvCC,UAAUN,SAASM,QAAQ;wBAC3BC,MAAMZ;wBACNa,gBAAgBR,SAASQ,cAAc;wBACvCC,qBAAqBrB,OAAOqB,mBAAmB;oBACjD;oBACA,MAAM5B,oBAAoB;wBACxBa,IAAIU;wBACJI,gBAAgBR,SAASQ,cAAc;wBACvCN;wBACAQ,aAAaT;oBACf;oBACA,OAAO,MAAMf,qBAAqB;wBAChCsB,gBAAgBR,SAASQ,cAAc;wBACvCP;oBACF;gBACF;gBACA,IAAIE,OAAOQ,OAAO,KAAK,SAASrB,SAAS;qBACpCC,WAAW;YAClB,EAAE,OAAOqB,OAAO;gBACd,4EAA4E;gBAC5E,mEAAmE;gBACnEpB,WAAW;gBACXZ,SAASiC,IAAI,CACX;oBAACC,KAAKF;oBAAOJ,gBAAgBR,SAASQ,cAAc;gBAAA,GACpD;YAEJ;YACApB,OAAO2B,mBAAmB;QAC5B;IACF;IAEA,OAAO;QAAC1B;QAASC;QAAOC;QAASC;IAAO;AAC1C"}
@@ -0,0 +1,11 @@
1
+ export interface CronSchedule {
2
+ subscriptionId: string;
3
+ workspaceId: string;
4
+ cronExpression: string;
5
+ timezone: string;
6
+ nextFireAt: Date;
7
+ lastFiredAt: Date | null;
8
+ createdAt: Date;
9
+ updatedAt: Date;
10
+ }
11
+ //# sourceMappingURL=cron-schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-schedule.d.ts","sourceRoot":"","sources":["../../../src/core/entities/cron-schedule.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=cron-schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/cron-schedule.ts"],"sourcesContent":["export interface CronSchedule {\n subscriptionId: string;\n workspaceId: string;\n cronExpression: string;\n timezone: string;\n nextFireAt: Date;\n lastFiredAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n"],"names":[],"mappings":"AAAA,WASC"}
@@ -0,0 +1,23 @@
1
+ import type { JobListenerMatcherKind } from './job-listener-subscription.js';
2
+ export declare const triggerDecisionOutcomes: readonly ["triggered", "filter-error", "dispatch-error"];
3
+ export type TriggerDecisionOutcome = (typeof triggerDecisionOutcomes)[number];
4
+ export type TriggerDecisionSubscriptionKind = 'trigger' | 'listener';
5
+ export interface TriggerDecision {
6
+ id: string;
7
+ receivedEventId: string;
8
+ subscriptionKind: TriggerDecisionSubscriptionKind;
9
+ subscriptionId: string;
10
+ subscriptionName: string;
11
+ workflowDefinitionId: string | null;
12
+ projectId: string | null;
13
+ workflowRunId: string | null;
14
+ jobId: string | null;
15
+ matcherKind: JobListenerMatcherKind | null;
16
+ matcherOrdinal: number | null;
17
+ decision: TriggerDecisionOutcome;
18
+ runId: string | null;
19
+ runName: string | null;
20
+ reason: string | null;
21
+ createdAt: Date;
22
+ }
23
+ //# sourceMappingURL=decision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../../src/core/entities/decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,uBAAuB,0DAA2D,CAAC;AAChG,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,MAAM,MAAM,+BAA+B,GAAG,SAAS,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,+BAA+B,CAAC;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC3C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,7 @@
1
+ export const triggerDecisionOutcomes = [
2
+ 'triggered',
3
+ 'filter-error',
4
+ 'dispatch-error'
5
+ ];
6
+
7
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/decision.ts"],"sourcesContent":["import type {JobListenerMatcherKind} from './job-listener-subscription.js';\n\nexport const triggerDecisionOutcomes = ['triggered', 'filter-error', 'dispatch-error'] as const;\nexport type TriggerDecisionOutcome = (typeof triggerDecisionOutcomes)[number];\nexport type TriggerDecisionSubscriptionKind = 'trigger' | 'listener';\n\nexport interface TriggerDecision {\n id: string;\n receivedEventId: string;\n subscriptionKind: TriggerDecisionSubscriptionKind;\n subscriptionId: string;\n subscriptionName: string;\n workflowDefinitionId: string | null;\n projectId: string | null;\n workflowRunId: string | null;\n jobId: string | null;\n matcherKind: JobListenerMatcherKind | null;\n matcherOrdinal: number | null;\n decision: TriggerDecisionOutcome;\n runId: string | null;\n runName: string | null;\n reason: string | null;\n createdAt: Date;\n}\n"],"names":["triggerDecisionOutcomes"],"mappings":"AAEA,OAAO,MAAMA,0BAA0B;IAAC;IAAa;IAAgB;CAAiB,CAAU"}
@@ -0,0 +1,3 @@
1
+ export type { JobListenerMatcherKind, JobListenerSubscription, } from './job-listener-subscription.js';
2
+ export type { TriggerSubscription } from './subscription.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/entities/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/index.ts"],"sourcesContent":["export type {\n JobListenerMatcherKind,\n JobListenerSubscription,\n} from './job-listener-subscription.js';\nexport type {TriggerSubscription} from './subscription.js';\n"],"names":[],"mappings":"AAIA,WAA2D"}
@@ -0,0 +1,14 @@
1
+ export type JobListenerMatcherKind = 'on' | 'until';
2
+ export interface JobListenerSubscription {
3
+ id: string;
4
+ workspaceId: string;
5
+ workflowRunId: string;
6
+ jobId: string;
7
+ kind: JobListenerMatcherKind;
8
+ matcherOrdinal: number;
9
+ source: string;
10
+ event: string;
11
+ config: Record<string, unknown>;
12
+ createdAt: Date;
13
+ }
14
+ //# sourceMappingURL=job-listener-subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-listener-subscription.d.ts","sourceRoot":"","sources":["../../../src/core/entities/job-listener-subscription.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,IAAI,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,sBAAsB,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=job-listener-subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/job-listener-subscription.ts"],"sourcesContent":["export type JobListenerMatcherKind = 'on' | 'until';\n\nexport interface JobListenerSubscription {\n id: string;\n workspaceId: string;\n workflowRunId: string;\n jobId: string;\n kind: JobListenerMatcherKind;\n matcherOrdinal: number;\n source: string;\n event: string;\n config: Record<string, unknown>;\n createdAt: Date;\n}\n"],"names":[],"mappings":"AAEA,WAWC"}
@@ -0,0 +1,28 @@
1
+ export declare const triggerEventOrigins: readonly ["integration", "manual", "cron"];
2
+ export type TriggerEventOrigin = (typeof triggerEventOrigins)[number];
3
+ export declare const triggerEventOutcomes: readonly ["received", "routed", "discarded", "failed", "errored"];
4
+ export type TriggerEventOutcome = (typeof triggerEventOutcomes)[number];
5
+ export interface TriggerReceivedEvent {
6
+ id: string;
7
+ eventRef: string;
8
+ origin: TriggerEventOrigin;
9
+ workspaceId: string;
10
+ provider: string | null;
11
+ source: string;
12
+ event: string;
13
+ deliveryId: string | null;
14
+ connectionId: string | null;
15
+ connectionName: string | null;
16
+ outcome: TriggerEventOutcome;
17
+ matchedCount: number;
18
+ payload: Record<string, unknown> | null;
19
+ receivedAt: Date;
20
+ processedAt: Date | null;
21
+ createdAt: Date;
22
+ }
23
+ /**
24
+ * Trigger event shape for list read models.
25
+ * It omits payload because webhook bodies can be large/untrusted and only detail views render them.
26
+ */
27
+ export type TriggerReceivedEventSummary = Omit<TriggerReceivedEvent, 'payload'>;
28
+ //# sourceMappingURL=received-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"received-event.d.ts","sourceRoot":"","sources":["../../../src/core/entities/received-event.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,4CAA6C,CAAC;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,oBAAoB,mEAMvB,CAAC;AACX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ export const triggerEventOrigins = [
2
+ 'integration',
3
+ 'manual',
4
+ 'cron'
5
+ ];
6
+ export const triggerEventOutcomes = [
7
+ 'received',
8
+ 'routed',
9
+ 'discarded',
10
+ 'failed',
11
+ 'errored'
12
+ ];
13
+
14
+ //# sourceMappingURL=received-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/received-event.ts"],"sourcesContent":["export const triggerEventOrigins = ['integration', 'manual', 'cron'] as const;\nexport type TriggerEventOrigin = (typeof triggerEventOrigins)[number];\n\nexport const triggerEventOutcomes = [\n 'received',\n 'routed',\n 'discarded',\n 'failed',\n 'errored',\n] as const;\nexport type TriggerEventOutcome = (typeof triggerEventOutcomes)[number];\n\nexport interface TriggerReceivedEvent {\n id: string;\n eventRef: string;\n origin: TriggerEventOrigin;\n workspaceId: string;\n provider: string | null;\n source: string;\n event: string;\n deliveryId: string | null;\n connectionId: string | null;\n connectionName: string | null;\n outcome: TriggerEventOutcome;\n matchedCount: number;\n payload: Record<string, unknown> | null;\n receivedAt: Date;\n processedAt: Date | null;\n createdAt: Date;\n}\n\n/**\n * Trigger event shape for list read models.\n * It omits payload because webhook bodies can be large/untrusted and only detail views render them.\n */\nexport type TriggerReceivedEventSummary = Omit<TriggerReceivedEvent, 'payload'>;\n"],"names":["triggerEventOrigins","triggerEventOutcomes"],"mappings":"AAAA,OAAO,MAAMA,sBAAsB;IAAC;IAAe;IAAU;CAAO,CAAU;AAG9E,OAAO,MAAMC,uBAAuB;IAClC;IACA;IACA;IACA;IACA;CACD,CAAU"}
@@ -0,0 +1,13 @@
1
+ export interface TriggerSubscription {
2
+ id: string;
3
+ workspaceId: string;
4
+ projectId: string;
5
+ workflowDefinitionId: string;
6
+ name: string;
7
+ source: string;
8
+ event: string;
9
+ config: Record<string, unknown>;
10
+ createdAt: Date;
11
+ updatedAt: Date;
12
+ }
13
+ //# sourceMappingURL=subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../../src/core/entities/subscription.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/subscription.ts"],"sourcesContent":["export interface TriggerSubscription {\n id: string;\n workspaceId: string;\n projectId: string;\n workflowDefinitionId: string;\n name: string;\n source: string;\n event: string;\n config: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n"],"names":[],"mappings":"AAAA,WAWC"}