@smthrs/triggers 0.0.0-stage → 1.0.0-rc.3

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 (226) hide show
  1. package/CHANGELOG.md +219 -0
  2. package/LICENSE +21 -0
  3. package/README.md +109 -2
  4. package/dist/cjs/CatchUp.d.ts +25 -0
  5. package/dist/cjs/CatchUp.d.ts.map +1 -0
  6. package/dist/cjs/CatchUp.js +72 -0
  7. package/dist/cjs/CatchUp.js.map +7 -0
  8. package/dist/cjs/Channel.d.ts +108 -0
  9. package/dist/cjs/Channel.d.ts.map +1 -0
  10. package/dist/cjs/Channel.js +25 -0
  11. package/dist/cjs/Channel.js.map +7 -0
  12. package/dist/cjs/ClaimDecision.d.ts +183 -0
  13. package/dist/cjs/ClaimDecision.d.ts.map +1 -0
  14. package/dist/cjs/ClaimDecision.js +144 -0
  15. package/dist/cjs/ClaimDecision.js.map +7 -0
  16. package/dist/cjs/Cron.d.ts +91 -0
  17. package/dist/cjs/Cron.d.ts.map +1 -0
  18. package/dist/cjs/Cron.js +108 -0
  19. package/dist/cjs/Cron.js.map +7 -0
  20. package/dist/cjs/DispatchReader.d.ts +77 -0
  21. package/dist/cjs/DispatchReader.d.ts.map +1 -0
  22. package/dist/cjs/DispatchReader.js +121 -0
  23. package/dist/cjs/DispatchReader.js.map +7 -0
  24. package/dist/cjs/Overlap.d.ts +40 -0
  25. package/dist/cjs/Overlap.d.ts.map +1 -0
  26. package/dist/cjs/Overlap.js +37 -0
  27. package/dist/cjs/Overlap.js.map +7 -0
  28. package/dist/cjs/Schedule.d.ts +96 -0
  29. package/dist/cjs/Schedule.d.ts.map +1 -0
  30. package/dist/cjs/Schedule.js +61 -0
  31. package/dist/cjs/Schedule.js.map +7 -0
  32. package/dist/cjs/Scheduler.d.ts +248 -0
  33. package/dist/cjs/Scheduler.d.ts.map +1 -0
  34. package/dist/cjs/Scheduler.js +647 -0
  35. package/dist/cjs/Scheduler.js.map +7 -0
  36. package/dist/cjs/SqlTriggerStore.d.ts +29 -0
  37. package/dist/cjs/SqlTriggerStore.d.ts.map +1 -0
  38. package/dist/cjs/SqlTriggerStore.js +483 -0
  39. package/dist/cjs/SqlTriggerStore.js.map +7 -0
  40. package/dist/cjs/Trigger.d.ts +81 -0
  41. package/dist/cjs/Trigger.d.ts.map +1 -0
  42. package/dist/cjs/Trigger.js +54 -0
  43. package/dist/cjs/Trigger.js.map +7 -0
  44. package/dist/cjs/TriggerError.d.ts +58 -0
  45. package/dist/cjs/TriggerError.d.ts.map +1 -0
  46. package/dist/cjs/TriggerError.js +83 -0
  47. package/dist/cjs/TriggerError.js.map +7 -0
  48. package/dist/cjs/TriggerStore.d.ts +411 -0
  49. package/dist/cjs/TriggerStore.d.ts.map +1 -0
  50. package/dist/cjs/TriggerStore.js +127 -0
  51. package/dist/cjs/TriggerStore.js.map +7 -0
  52. package/dist/cjs/Webhook.d.ts +118 -0
  53. package/dist/cjs/Webhook.d.ts.map +1 -0
  54. package/dist/cjs/Webhook.js +153 -0
  55. package/dist/cjs/Webhook.js.map +7 -0
  56. package/dist/cjs/index.d.ts +30 -0
  57. package/dist/cjs/index.d.ts.map +1 -0
  58. package/dist/cjs/index.js +57 -0
  59. package/dist/cjs/index.js.map +7 -0
  60. package/dist/cjs/internal/ActiveRuns.d.ts +51 -0
  61. package/dist/cjs/internal/ActiveRuns.d.ts.map +1 -0
  62. package/dist/cjs/internal/ActiveRuns.js +56 -0
  63. package/dist/cjs/internal/ActiveRuns.js.map +7 -0
  64. package/dist/cjs/internal/DueOccurrences.d.ts +32 -0
  65. package/dist/cjs/internal/DueOccurrences.d.ts.map +1 -0
  66. package/dist/cjs/internal/DueOccurrences.js +80 -0
  67. package/dist/cjs/internal/DueOccurrences.js.map +7 -0
  68. package/dist/cjs/internal/WallClock.d.ts +59 -0
  69. package/dist/cjs/internal/WallClock.d.ts.map +1 -0
  70. package/dist/cjs/internal/WallClock.js +132 -0
  71. package/dist/cjs/internal/WallClock.js.map +7 -0
  72. package/dist/cjs/migrations/0001_triggers.d.ts +15 -0
  73. package/dist/cjs/migrations/0001_triggers.d.ts.map +1 -0
  74. package/dist/cjs/migrations/0001_triggers.js +64 -0
  75. package/dist/cjs/migrations/0001_triggers.js.map +7 -0
  76. package/dist/cjs/migrations/0002_reservation_lease.d.ts +15 -0
  77. package/dist/cjs/migrations/0002_reservation_lease.d.ts.map +1 -0
  78. package/dist/cjs/migrations/0002_reservation_lease.js +41 -0
  79. package/dist/cjs/migrations/0002_reservation_lease.js.map +7 -0
  80. package/dist/cjs/migrations/0003_heartbeat.d.ts +16 -0
  81. package/dist/cjs/migrations/0003_heartbeat.d.ts.map +1 -0
  82. package/dist/cjs/migrations/0003_heartbeat.js +44 -0
  83. package/dist/cjs/migrations/0003_heartbeat.js.map +7 -0
  84. package/dist/cjs/migrations/0004_fire_run_index.d.ts +17 -0
  85. package/dist/cjs/migrations/0004_fire_run_index.d.ts.map +1 -0
  86. package/dist/cjs/migrations/0004_fire_run_index.js +40 -0
  87. package/dist/cjs/migrations/0004_fire_run_index.js.map +7 -0
  88. package/dist/cjs/migrations/index.d.ts +33 -0
  89. package/dist/cjs/migrations/index.d.ts.map +1 -0
  90. package/dist/cjs/migrations/index.js +50 -0
  91. package/dist/cjs/migrations/index.js.map +7 -0
  92. package/dist/cjs/package.json +1 -0
  93. package/dist/cjs/test/TestTriggers.d.ts +12 -0
  94. package/dist/cjs/test/TestTriggers.d.ts.map +1 -0
  95. package/dist/cjs/test/TestTriggers.js +421 -0
  96. package/dist/cjs/test/TestTriggers.js.map +7 -0
  97. package/dist/esm/CatchUp.d.ts +25 -0
  98. package/dist/esm/CatchUp.d.ts.map +1 -0
  99. package/dist/esm/CatchUp.js +52 -0
  100. package/dist/esm/CatchUp.js.map +1 -0
  101. package/dist/esm/Channel.d.ts +108 -0
  102. package/dist/esm/Channel.d.ts.map +1 -0
  103. package/dist/esm/Channel.js +19 -0
  104. package/dist/esm/Channel.js.map +1 -0
  105. package/dist/esm/ClaimDecision.d.ts +183 -0
  106. package/dist/esm/ClaimDecision.d.ts.map +1 -0
  107. package/dist/esm/ClaimDecision.js +172 -0
  108. package/dist/esm/ClaimDecision.js.map +1 -0
  109. package/dist/esm/Cron.d.ts +91 -0
  110. package/dist/esm/Cron.d.ts.map +1 -0
  111. package/dist/esm/Cron.js +132 -0
  112. package/dist/esm/Cron.js.map +1 -0
  113. package/dist/esm/DispatchReader.d.ts +77 -0
  114. package/dist/esm/DispatchReader.d.ts.map +1 -0
  115. package/dist/esm/DispatchReader.js +152 -0
  116. package/dist/esm/DispatchReader.js.map +1 -0
  117. package/dist/esm/Overlap.d.ts +40 -0
  118. package/dist/esm/Overlap.d.ts.map +1 -0
  119. package/dist/esm/Overlap.js +31 -0
  120. package/dist/esm/Overlap.js.map +1 -0
  121. package/dist/esm/Schedule.d.ts +96 -0
  122. package/dist/esm/Schedule.d.ts.map +1 -0
  123. package/dist/esm/Schedule.js +73 -0
  124. package/dist/esm/Schedule.js.map +1 -0
  125. package/dist/esm/Scheduler.d.ts +248 -0
  126. package/dist/esm/Scheduler.d.ts.map +1 -0
  127. package/dist/esm/Scheduler.js +734 -0
  128. package/dist/esm/Scheduler.js.map +1 -0
  129. package/dist/esm/SqlTriggerStore.d.ts +29 -0
  130. package/dist/esm/SqlTriggerStore.d.ts.map +1 -0
  131. package/dist/esm/SqlTriggerStore.js +483 -0
  132. package/dist/esm/SqlTriggerStore.js.map +1 -0
  133. package/dist/esm/Trigger.d.ts +81 -0
  134. package/dist/esm/Trigger.d.ts.map +1 -0
  135. package/dist/esm/Trigger.js +56 -0
  136. package/dist/esm/Trigger.js.map +1 -0
  137. package/dist/esm/TriggerError.d.ts +58 -0
  138. package/dist/esm/TriggerError.d.ts.map +1 -0
  139. package/dist/esm/TriggerError.js +110 -0
  140. package/dist/esm/TriggerError.js.map +1 -0
  141. package/dist/esm/TriggerStore.d.ts +411 -0
  142. package/dist/esm/TriggerStore.d.ts.map +1 -0
  143. package/dist/esm/TriggerStore.js +209 -0
  144. package/dist/esm/TriggerStore.js.map +1 -0
  145. package/dist/esm/Webhook.d.ts +118 -0
  146. package/dist/esm/Webhook.d.ts.map +1 -0
  147. package/dist/esm/Webhook.js +186 -0
  148. package/dist/esm/Webhook.js.map +1 -0
  149. package/dist/esm/index.d.ts +30 -0
  150. package/dist/esm/index.d.ts.map +1 -0
  151. package/dist/esm/index.js +30 -0
  152. package/dist/esm/index.js.map +1 -0
  153. package/dist/esm/internal/ActiveRuns.d.ts +51 -0
  154. package/dist/esm/internal/ActiveRuns.d.ts.map +1 -0
  155. package/dist/esm/internal/ActiveRuns.js +34 -0
  156. package/dist/esm/internal/ActiveRuns.js.map +1 -0
  157. package/dist/esm/internal/DueOccurrences.d.ts +32 -0
  158. package/dist/esm/internal/DueOccurrences.d.ts.map +1 -0
  159. package/dist/esm/internal/DueOccurrences.js +55 -0
  160. package/dist/esm/internal/DueOccurrences.js.map +1 -0
  161. package/dist/esm/internal/WallClock.d.ts +59 -0
  162. package/dist/esm/internal/WallClock.d.ts.map +1 -0
  163. package/dist/esm/internal/WallClock.js +155 -0
  164. package/dist/esm/internal/WallClock.js.map +1 -0
  165. package/dist/esm/migrations/0001_triggers.d.ts +15 -0
  166. package/dist/esm/migrations/0001_triggers.d.ts.map +1 -0
  167. package/dist/esm/migrations/0001_triggers.js +42 -0
  168. package/dist/esm/migrations/0001_triggers.js.map +1 -0
  169. package/dist/esm/migrations/0002_reservation_lease.d.ts +15 -0
  170. package/dist/esm/migrations/0002_reservation_lease.d.ts.map +1 -0
  171. package/dist/esm/migrations/0002_reservation_lease.js +19 -0
  172. package/dist/esm/migrations/0002_reservation_lease.js.map +1 -0
  173. package/dist/esm/migrations/0003_heartbeat.d.ts +16 -0
  174. package/dist/esm/migrations/0003_heartbeat.d.ts.map +1 -0
  175. package/dist/esm/migrations/0003_heartbeat.js +23 -0
  176. package/dist/esm/migrations/0003_heartbeat.js.map +1 -0
  177. package/dist/esm/migrations/0004_fire_run_index.d.ts +17 -0
  178. package/dist/esm/migrations/0004_fire_run_index.d.ts.map +1 -0
  179. package/dist/esm/migrations/0004_fire_run_index.js +20 -0
  180. package/dist/esm/migrations/0004_fire_run_index.js.map +1 -0
  181. package/dist/esm/migrations/index.d.ts +33 -0
  182. package/dist/esm/migrations/index.d.ts.map +1 -0
  183. package/dist/esm/migrations/index.js +37 -0
  184. package/dist/esm/migrations/index.js.map +1 -0
  185. package/dist/esm/test/TestTriggers.d.ts +12 -0
  186. package/dist/esm/test/TestTriggers.d.ts.map +1 -0
  187. package/dist/esm/test/TestTriggers.js +439 -0
  188. package/dist/esm/test/TestTriggers.js.map +1 -0
  189. package/docs/README.md +140 -0
  190. package/docs/api.md +1186 -0
  191. package/docs/concepts/channels.md +103 -0
  192. package/docs/concepts/claim-protocol.md +229 -0
  193. package/docs/concepts/policies.md +124 -0
  194. package/docs/concepts/schedules.md +134 -0
  195. package/docs/guides/choose-a-policy.md +113 -0
  196. package/docs/guides/declare-a-trigger.md +136 -0
  197. package/docs/guides/ingest-a-webhook.md +164 -0
  198. package/docs/guides/run-the-scheduler.md +173 -0
  199. package/docs/guides/testing.md +157 -0
  200. package/docs/installation.md +81 -0
  201. package/docs/quickstart.md +163 -0
  202. package/docs/troubleshooting.md +281 -0
  203. package/package.json +241 -3
  204. package/src/CatchUp.ts +73 -0
  205. package/src/Channel.ts +121 -0
  206. package/src/ClaimDecision.ts +303 -0
  207. package/src/Cron.ts +173 -0
  208. package/src/DispatchReader.ts +179 -0
  209. package/src/Overlap.ts +53 -0
  210. package/src/Schedule.ts +112 -0
  211. package/src/Scheduler.ts +1154 -0
  212. package/src/SqlTriggerStore.ts +638 -0
  213. package/src/Trigger.ts +84 -0
  214. package/src/TriggerError.ts +129 -0
  215. package/src/TriggerStore.ts +514 -0
  216. package/src/Webhook.ts +270 -0
  217. package/src/index.ts +30 -0
  218. package/src/internal/ActiveRuns.ts +83 -0
  219. package/src/internal/DueOccurrences.ts +101 -0
  220. package/src/internal/WallClock.ts +172 -0
  221. package/src/migrations/0001_triggers.ts +43 -0
  222. package/src/migrations/0002_reservation_lease.ts +20 -0
  223. package/src/migrations/0003_heartbeat.ts +24 -0
  224. package/src/migrations/0004_fire_run_index.ts +21 -0
  225. package/src/migrations/index.ts +40 -0
  226. package/src/test/TestTriggers.ts +563 -0
package/package.json CHANGED
@@ -1,6 +1,244 @@
1
1
  {
2
2
  "name": "@smthrs/triggers",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "type": "module",
4
+ "version": "1.0.0-rc.3",
5
+ "license": "MIT",
6
+ "smthrs": {
7
+ "group": "agent"
8
+ },
9
+ "description": "Durable cron triggers and channel contracts for flows",
10
+ "homepage": "https://github.com/smithersai/smithers",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/smithersai/smithers.git",
14
+ "directory": "packages/smithers/agent/triggers"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/smithersai/smithers/issues"
18
+ },
19
+ "tags": [
20
+ "typescript",
21
+ "effect",
22
+ "flow",
23
+ "triggers"
24
+ ],
25
+ "keywords": [
26
+ "typescript",
27
+ "effect",
28
+ "flow",
29
+ "triggers"
30
+ ],
31
+ "engines": {
32
+ "node": ">=26.4.0"
33
+ },
34
+ "sideEffects": [],
35
+ "exports": {
36
+ "./package.json": "./package.json",
37
+ ".": {
38
+ "import": {
39
+ "types": "./dist/esm/index.d.ts",
40
+ "default": "./dist/esm/index.js"
41
+ },
42
+ "require": {
43
+ "types": "./dist/cjs/index.d.ts",
44
+ "default": "./dist/cjs/index.js"
45
+ }
46
+ },
47
+ "./migrations/*": null,
48
+ "./internal/*": null,
49
+ "./*/index": null,
50
+ "./CatchUp": {
51
+ "import": {
52
+ "types": "./dist/esm/CatchUp.d.ts",
53
+ "default": "./dist/esm/CatchUp.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/cjs/CatchUp.d.ts",
57
+ "default": "./dist/cjs/CatchUp.js"
58
+ }
59
+ },
60
+ "./Channel": {
61
+ "import": {
62
+ "types": "./dist/esm/Channel.d.ts",
63
+ "default": "./dist/esm/Channel.js"
64
+ },
65
+ "require": {
66
+ "types": "./dist/cjs/Channel.d.ts",
67
+ "default": "./dist/cjs/Channel.js"
68
+ }
69
+ },
70
+ "./Cron": {
71
+ "import": {
72
+ "types": "./dist/esm/Cron.d.ts",
73
+ "default": "./dist/esm/Cron.js"
74
+ },
75
+ "require": {
76
+ "types": "./dist/cjs/Cron.d.ts",
77
+ "default": "./dist/cjs/Cron.js"
78
+ }
79
+ },
80
+ "./DispatchReader": {
81
+ "import": {
82
+ "types": "./dist/esm/DispatchReader.d.ts",
83
+ "default": "./dist/esm/DispatchReader.js"
84
+ },
85
+ "require": {
86
+ "types": "./dist/cjs/DispatchReader.d.ts",
87
+ "default": "./dist/cjs/DispatchReader.js"
88
+ }
89
+ },
90
+ "./Overlap": {
91
+ "import": {
92
+ "types": "./dist/esm/Overlap.d.ts",
93
+ "default": "./dist/esm/Overlap.js"
94
+ },
95
+ "require": {
96
+ "types": "./dist/cjs/Overlap.d.ts",
97
+ "default": "./dist/cjs/Overlap.js"
98
+ }
99
+ },
100
+ "./Schedule": {
101
+ "import": {
102
+ "types": "./dist/esm/Schedule.d.ts",
103
+ "default": "./dist/esm/Schedule.js"
104
+ },
105
+ "require": {
106
+ "types": "./dist/cjs/Schedule.d.ts",
107
+ "default": "./dist/cjs/Schedule.js"
108
+ }
109
+ },
110
+ "./Scheduler": {
111
+ "import": {
112
+ "types": "./dist/esm/Scheduler.d.ts",
113
+ "default": "./dist/esm/Scheduler.js"
114
+ },
115
+ "require": {
116
+ "types": "./dist/cjs/Scheduler.d.ts",
117
+ "default": "./dist/cjs/Scheduler.js"
118
+ }
119
+ },
120
+ "./SqlTriggerStore": {
121
+ "import": {
122
+ "types": "./dist/esm/SqlTriggerStore.d.ts",
123
+ "default": "./dist/esm/SqlTriggerStore.js"
124
+ },
125
+ "require": {
126
+ "types": "./dist/cjs/SqlTriggerStore.d.ts",
127
+ "default": "./dist/cjs/SqlTriggerStore.js"
128
+ }
129
+ },
130
+ "./Trigger": {
131
+ "import": {
132
+ "types": "./dist/esm/Trigger.d.ts",
133
+ "default": "./dist/esm/Trigger.js"
134
+ },
135
+ "require": {
136
+ "types": "./dist/cjs/Trigger.d.ts",
137
+ "default": "./dist/cjs/Trigger.js"
138
+ }
139
+ },
140
+ "./TriggerError": {
141
+ "import": {
142
+ "types": "./dist/esm/TriggerError.d.ts",
143
+ "default": "./dist/esm/TriggerError.js"
144
+ },
145
+ "require": {
146
+ "types": "./dist/cjs/TriggerError.d.ts",
147
+ "default": "./dist/cjs/TriggerError.js"
148
+ }
149
+ },
150
+ "./TriggerStore": {
151
+ "import": {
152
+ "types": "./dist/esm/TriggerStore.d.ts",
153
+ "default": "./dist/esm/TriggerStore.js"
154
+ },
155
+ "require": {
156
+ "types": "./dist/cjs/TriggerStore.d.ts",
157
+ "default": "./dist/cjs/TriggerStore.js"
158
+ }
159
+ },
160
+ "./Webhook": {
161
+ "import": {
162
+ "types": "./dist/esm/Webhook.d.ts",
163
+ "default": "./dist/esm/Webhook.js"
164
+ },
165
+ "require": {
166
+ "types": "./dist/cjs/Webhook.d.ts",
167
+ "default": "./dist/cjs/Webhook.js"
168
+ }
169
+ },
170
+ "./index": {
171
+ "import": {
172
+ "types": "./dist/esm/index.d.ts",
173
+ "default": "./dist/esm/index.js"
174
+ },
175
+ "require": {
176
+ "types": "./dist/cjs/index.d.ts",
177
+ "default": "./dist/cjs/index.js"
178
+ }
179
+ },
180
+ "./test/TestTriggers": {
181
+ "import": {
182
+ "types": "./dist/esm/test/TestTriggers.d.ts",
183
+ "default": "./dist/esm/test/TestTriggers.js"
184
+ },
185
+ "require": {
186
+ "types": "./dist/cjs/test/TestTriggers.d.ts",
187
+ "default": "./dist/cjs/test/TestTriggers.js"
188
+ }
189
+ }
190
+ },
191
+ "files": [
192
+ "src/**/*.ts",
193
+ "dist/**/*.js",
194
+ "dist/**/*.js.map",
195
+ "dist/**/*.d.ts",
196
+ "dist/**/*.d.ts.map",
197
+ "dist/**/package.json",
198
+ "LICENSE",
199
+ "README.md",
200
+ "CHANGELOG.md",
201
+ "docs/"
202
+ ],
203
+ "publishConfig": {
204
+ "access": "public",
205
+ "provenance": true,
206
+ "tag": "next"
207
+ },
208
+ "dependencies": {
209
+ "@smthrs/control": "1.0.0-rc.3",
210
+ "@smthrs/database": "1.0.0-rc.3"
211
+ },
212
+ "peerDependencies": {
213
+ "effect": "4.0.0-rc.115"
214
+ },
215
+ "devDependencies": {
216
+ "@effect/language-service": "0.87.2",
217
+ "@effect/vitest": "4.0.0-rc.115",
218
+ "@eslint/js": "9.39.5",
219
+ "@types/node": "26.4.1",
220
+ "@vitest/coverage-v8": "5.0.0",
221
+ "dprint": "0.57.1",
222
+ "effect": "4.0.0-rc.115",
223
+ "esbuild": "0.28.2",
224
+ "eslint": "9.39.5",
225
+ "eslint-import-resolver-typescript": "4.4.5",
226
+ "eslint-plugin-import": "2.32.0",
227
+ "eslint-plugin-jsdoc": "64.3.4",
228
+ "eslint-plugin-unicorn": "65.0.0",
229
+ "madge": "8.0.0",
230
+ "typescript": "5.9.3",
231
+ "typescript-eslint": "8.69.0",
232
+ "vitest": "5.0.0"
233
+ },
234
+ "scripts": {
235
+ "lint": "eslint src --max-warnings=0 && dprint check",
236
+ "format": "dprint fmt",
237
+ "build": "node scripts/build.mjs",
238
+ "check": "tsc -b tsconfig.json && tsc -p tsconfig.test.json --noEmit",
239
+ "circular": "node scripts/circular.mjs",
240
+ "test": "vitest",
241
+ "coverage": "node ../../flows/database/scripts/test-matrix.mjs",
242
+ "test:matrix": "node ../../flows/database/scripts/test-matrix.mjs"
243
+ }
6
244
  }
package/src/CatchUp.ts ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Pure catch-up policy decisions.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+
7
+ import * as Effect from "effect/Effect"
8
+ import type { Cron } from "./Cron.ts"
9
+ import * as CronSchedule from "./Cron.ts"
10
+ import type { CatchUp as Policy } from "./Schedule.ts"
11
+ import { TriggerError } from "./TriggerError.ts"
12
+
13
+ /**
14
+ * The occurrences a trigger owes since it last fired, bounded by
15
+ * `maxCatchUp` and by the policy named in `Schedule.CatchUp`: `none` owes
16
+ * nothing, `one` owes only the most recent, and `all` owes every missed tick.
17
+ *
18
+ * Every policy answers to `maxCatchUp`, `one` included: a bound of zero says
19
+ * no occurrence may be caught up, so a missed occurrence under `one` is
20
+ * `catch_up_bound_exceeded` exactly as three missed occurrences under `all`
21
+ * are. The bound is validated before any policy branch, so an unusable bound
22
+ * is refused even where the policy owes nothing.
23
+ *
24
+ * @category computation
25
+ * @since 0.1.0
26
+ */
27
+ export const occurrences = (
28
+ policy: Policy,
29
+ maxCatchUp: number,
30
+ lastFiredAt: Date | undefined,
31
+ now: Date,
32
+ cron: Cron
33
+ ): Effect.Effect<ReadonlyArray<Date>, TriggerError> => {
34
+ if (!Number.isSafeInteger(maxCatchUp) || maxCatchUp < 0) {
35
+ return Effect.fail(
36
+ new TriggerError({
37
+ code: "catch_up_bound_exceeded",
38
+ message: `maxCatchUp must be a non-negative safe integer, received ${maxCatchUp}`,
39
+ path: "maxCatchUp"
40
+ })
41
+ )
42
+ }
43
+ if (lastFiredAt === undefined) return Effect.succeed([])
44
+ if (policy === "none") return Effect.succeed([])
45
+ if (policy === "one") {
46
+ return CronSchedule.previousAtOrBefore(cron, now).pipe(
47
+ Effect.flatMap((latest) =>
48
+ latest.getTime() <= lastFiredAt.getTime()
49
+ ? Effect.succeed<ReadonlyArray<Date>>([])
50
+ : maxCatchUp < 1
51
+ ? Effect.fail(
52
+ new TriggerError({
53
+ code: "catch_up_bound_exceeded",
54
+ message: `missed 1 occurrence; maxCatchUp is ${maxCatchUp}`
55
+ })
56
+ )
57
+ : Effect.succeed<ReadonlyArray<Date>>([latest])
58
+ )
59
+ )
60
+ }
61
+ return CronSchedule.occurrencesBetween(cron, lastFiredAt, now, maxCatchUp + 1).pipe(
62
+ Effect.flatMap((missed) =>
63
+ missed.length > maxCatchUp
64
+ ? Effect.fail(
65
+ new TriggerError({
66
+ code: "catch_up_bound_exceeded",
67
+ message: `missed ${missed.length} occurrences; maxCatchUp is ${maxCatchUp}`
68
+ })
69
+ )
70
+ : Effect.succeed(missed)
71
+ )
72
+ )
73
+ }
package/src/Channel.ts ADDED
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Authority-free channel declarations.
3
+ *
4
+ * A channel authenticates opaque transport input, maps verified payloads to
5
+ * control-plane starts or signals, and may project run state outbound. It
6
+ * carries no execution authority: the target flow's envelope and permission
7
+ * checks apply unchanged.
8
+ *
9
+ * @see packages/smithers/agent/triggers/docs/api.md
10
+ * @since 0.1.0
11
+ */
12
+
13
+ import type { IdempotencyKey } from "@smthrs/control/ControlSchema"
14
+ import type { CredentialRef } from "@smthrs/control/Credential"
15
+ import type * as Effect from "effect/Effect"
16
+ import type * as Redacted from "effect/Redacted"
17
+ import type * as Schema from "effect/Schema"
18
+ import type { TriggerError } from "./TriggerError.ts"
19
+
20
+ /**
21
+ * Opaque inbound transport data. Verification must inspect this value before
22
+ * any payload decoding occurs.
23
+ *
24
+ * @category models
25
+ * @since 0.1.0
26
+ */
27
+ export interface RawInbound {
28
+ readonly body: Uint8Array
29
+ readonly headers: Readonly<Record<string, string | undefined>>
30
+ readonly idempotencyKey: IdempotencyKey
31
+ }
32
+
33
+ /**
34
+ * A verified request that starts a flow.
35
+ *
36
+ * @category models
37
+ * @since 0.1.0
38
+ */
39
+ export interface Start {
40
+ readonly start: {
41
+ readonly flowId: string
42
+ readonly input: unknown
43
+ }
44
+ }
45
+
46
+ /**
47
+ * A verified request that resolves a waiting flow step.
48
+ *
49
+ * @category models
50
+ * @since 0.1.0
51
+ */
52
+ export interface Signal {
53
+ readonly signal: {
54
+ readonly runId: string
55
+ readonly stepId: string
56
+ readonly value: unknown
57
+ }
58
+ }
59
+
60
+ /**
61
+ * The only operations an inbound channel may request.
62
+ *
63
+ * @category models
64
+ * @since 0.1.0
65
+ */
66
+ export type Inbound = Start | Signal
67
+
68
+ /**
69
+ * Authenticates raw request bytes and headers against a credential reference.
70
+ *
71
+ * The credential arrives as a redacted reference rather than a secret, and it
72
+ * arrives per request rather than at declaration time: a verifier resolves it
73
+ * through the host's resolver when it needs the bytes. Dropping this parameter
74
+ * left a verifier no way to reach a secret except by closing over it in plain
75
+ * memory at declaration time, which is the shape the reference exists to
76
+ * prevent. `packages/smithers/control/src/WebhookChannel.ts` states the same contract
77
+ * for the control-plane side of the boundary.
78
+ *
79
+ * @category models
80
+ * @since 0.1.0
81
+ */
82
+ export type Verify = (
83
+ raw: RawInbound,
84
+ credential: Redacted.Redacted<CredentialRef>
85
+ ) => Effect.Effect<void, TriggerError>
86
+
87
+ /**
88
+ * An authority-free bidirectional channel declaration.
89
+ *
90
+ * `inbound` only describes a control-plane start or signal. It cannot supply
91
+ * capabilities, grants, or an alternate execution envelope.
92
+ *
93
+ * @category declarations
94
+ * @since 0.1.0
95
+ */
96
+ export interface Channel<Payload, Run = never, Outbound = never> {
97
+ readonly name: string
98
+ readonly verify: Verify
99
+ readonly inbound: (payload: Payload) => Inbound
100
+ readonly outbound?: ((run: Run) => Outbound) | undefined
101
+ }
102
+
103
+ /**
104
+ * Configuration for a schema-declared channel.
105
+ *
106
+ * @category models
107
+ * @since 0.1.0
108
+ */
109
+ export interface Config<Payload, Run = never, Outbound = never> extends Channel<Payload, Run, Outbound> {
110
+ readonly schema: Schema.Schema<Payload>
111
+ }
112
+
113
+ /**
114
+ * Declares a channel without adding authority or execution behavior.
115
+ *
116
+ * @category constructors
117
+ * @since 0.1.0
118
+ */
119
+ export const make = <Payload, Run = never, Outbound = never>(
120
+ config: Channel<Payload, Run, Outbound>
121
+ ): Channel<Payload, Run, Outbound> => config