@relayflows/surface 2.0.8 → 2.0.10

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 (343) hide show
  1. package/README.md +3 -2
  2. package/dist/completion.d.ts +2 -0
  3. package/dist/completion.d.ts.map +1 -1
  4. package/dist/context.d.ts +29 -4
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/effect-transport.d.ts +22 -0
  7. package/dist/effect-transport.d.ts.map +1 -0
  8. package/dist/effect-transport.js +42 -0
  9. package/dist/effect-transport.js.map +1 -0
  10. package/dist/flow.d.ts +30 -5
  11. package/dist/flow.d.ts.map +1 -1
  12. package/dist/flow.js +58 -9
  13. package/dist/flow.js.map +1 -1
  14. package/dist/helper-clients.d.ts +86 -0
  15. package/dist/helper-clients.d.ts.map +1 -0
  16. package/dist/helper-clients.js +30 -0
  17. package/dist/helper-clients.js.map +1 -0
  18. package/dist/helpers/airtable.d.ts +4 -0
  19. package/dist/helpers/airtable.d.ts.map +1 -0
  20. package/dist/helpers/airtable.js +5 -0
  21. package/dist/helpers/airtable.js.map +1 -0
  22. package/dist/helpers/asana.d.ts +5 -0
  23. package/dist/helpers/asana.d.ts.map +1 -0
  24. package/dist/helpers/asana.js +6 -0
  25. package/dist/helpers/asana.js.map +1 -0
  26. package/dist/helpers/azure-blob.d.ts +5 -0
  27. package/dist/helpers/azure-blob.d.ts.map +1 -0
  28. package/dist/helpers/azure-blob.js +6 -0
  29. package/dist/helpers/azure-blob.js.map +1 -0
  30. package/dist/helpers/box.d.ts +5 -0
  31. package/dist/helpers/box.d.ts.map +1 -0
  32. package/dist/helpers/box.js +6 -0
  33. package/dist/helpers/box.js.map +1 -0
  34. package/dist/helpers/calendly.d.ts +5 -0
  35. package/dist/helpers/calendly.d.ts.map +1 -0
  36. package/dist/helpers/calendly.js +6 -0
  37. package/dist/helpers/calendly.js.map +1 -0
  38. package/dist/helpers/clickup.d.ts +5 -0
  39. package/dist/helpers/clickup.d.ts.map +1 -0
  40. package/dist/helpers/clickup.js +6 -0
  41. package/dist/helpers/clickup.js.map +1 -0
  42. package/dist/helpers/clients.d.ts +3 -0
  43. package/dist/helpers/clients.d.ts.map +1 -0
  44. package/dist/helpers/clients.js +46 -0
  45. package/dist/helpers/clients.js.map +1 -0
  46. package/dist/helpers/cloudflare.d.ts +5 -0
  47. package/dist/helpers/cloudflare.d.ts.map +1 -0
  48. package/dist/helpers/cloudflare.js +6 -0
  49. package/dist/helpers/cloudflare.js.map +1 -0
  50. package/dist/helpers/confluence.d.ts +5 -0
  51. package/dist/helpers/confluence.d.ts.map +1 -0
  52. package/dist/helpers/confluence.js +6 -0
  53. package/dist/helpers/confluence.js.map +1 -0
  54. package/dist/helpers/daytona.d.ts +5 -0
  55. package/dist/helpers/daytona.d.ts.map +1 -0
  56. package/dist/helpers/daytona.js +6 -0
  57. package/dist/helpers/daytona.js.map +1 -0
  58. package/dist/helpers/docker-hub.d.ts +4 -0
  59. package/dist/helpers/docker-hub.d.ts.map +1 -0
  60. package/dist/helpers/docker-hub.js +5 -0
  61. package/dist/helpers/docker-hub.js.map +1 -0
  62. package/dist/helpers/dropbox.d.ts +5 -0
  63. package/dist/helpers/dropbox.d.ts.map +1 -0
  64. package/dist/helpers/dropbox.js +6 -0
  65. package/dist/helpers/dropbox.js.map +1 -0
  66. package/dist/helpers/fathom.d.ts +4 -0
  67. package/dist/helpers/fathom.d.ts.map +1 -0
  68. package/dist/helpers/fathom.js +5 -0
  69. package/dist/helpers/fathom.js.map +1 -0
  70. package/dist/helpers/gcp.d.ts +4 -0
  71. package/dist/helpers/gcp.d.ts.map +1 -0
  72. package/dist/helpers/gcp.js +5 -0
  73. package/dist/helpers/gcp.js.map +1 -0
  74. package/dist/helpers/gcs.d.ts +5 -0
  75. package/dist/helpers/gcs.d.ts.map +1 -0
  76. package/dist/helpers/gcs.js +6 -0
  77. package/dist/helpers/gcs.js.map +1 -0
  78. package/dist/helpers/github.d.ts +5 -0
  79. package/dist/helpers/github.d.ts.map +1 -0
  80. package/dist/helpers/github.js +6 -0
  81. package/dist/helpers/github.js.map +1 -0
  82. package/dist/helpers/gitlab.d.ts +5 -0
  83. package/dist/helpers/gitlab.d.ts.map +1 -0
  84. package/dist/helpers/gitlab.js +6 -0
  85. package/dist/helpers/gitlab.js.map +1 -0
  86. package/dist/helpers/gmail.d.ts +5 -0
  87. package/dist/helpers/gmail.d.ts.map +1 -0
  88. package/dist/helpers/gmail.js +6 -0
  89. package/dist/helpers/gmail.js.map +1 -0
  90. package/dist/helpers/google-calendar.d.ts +5 -0
  91. package/dist/helpers/google-calendar.d.ts.map +1 -0
  92. package/dist/helpers/google-calendar.js +6 -0
  93. package/dist/helpers/google-calendar.js.map +1 -0
  94. package/dist/helpers/google-drive.d.ts +5 -0
  95. package/dist/helpers/google-drive.d.ts.map +1 -0
  96. package/dist/helpers/google-drive.js +6 -0
  97. package/dist/helpers/google-drive.js.map +1 -0
  98. package/dist/helpers/granola.d.ts +5 -0
  99. package/dist/helpers/granola.d.ts.map +1 -0
  100. package/dist/helpers/granola.js +6 -0
  101. package/dist/helpers/granola.js.map +1 -0
  102. package/dist/helpers/hubspot.d.ts +5 -0
  103. package/dist/helpers/hubspot.d.ts.map +1 -0
  104. package/dist/helpers/hubspot.js +6 -0
  105. package/dist/helpers/hubspot.js.map +1 -0
  106. package/dist/helpers/index.d.ts +155 -0
  107. package/dist/helpers/index.d.ts.map +1 -0
  108. package/dist/helpers/index.js +105 -0
  109. package/dist/helpers/index.js.map +1 -0
  110. package/dist/helpers/intercom.d.ts +5 -0
  111. package/dist/helpers/intercom.d.ts.map +1 -0
  112. package/dist/helpers/intercom.js +6 -0
  113. package/dist/helpers/intercom.js.map +1 -0
  114. package/dist/helpers/jira.d.ts +5 -0
  115. package/dist/helpers/jira.d.ts.map +1 -0
  116. package/dist/helpers/jira.js +6 -0
  117. package/dist/helpers/jira.js.map +1 -0
  118. package/dist/helpers/linear.d.ts +5 -0
  119. package/dist/helpers/linear.d.ts.map +1 -0
  120. package/dist/helpers/linear.js +6 -0
  121. package/dist/helpers/linear.js.map +1 -0
  122. package/dist/helpers/mailgun.d.ts +5 -0
  123. package/dist/helpers/mailgun.d.ts.map +1 -0
  124. package/dist/helpers/mailgun.js +6 -0
  125. package/dist/helpers/mailgun.js.map +1 -0
  126. package/dist/helpers/mixpanel.d.ts +5 -0
  127. package/dist/helpers/mixpanel.d.ts.map +1 -0
  128. package/dist/helpers/mixpanel.js +6 -0
  129. package/dist/helpers/mixpanel.js.map +1 -0
  130. package/dist/helpers/neon.d.ts +4 -0
  131. package/dist/helpers/neon.d.ts.map +1 -0
  132. package/dist/helpers/neon.js +5 -0
  133. package/dist/helpers/neon.js.map +1 -0
  134. package/dist/helpers/notion.d.ts +5 -0
  135. package/dist/helpers/notion.d.ts.map +1 -0
  136. package/dist/helpers/notion.js +6 -0
  137. package/dist/helpers/notion.js.map +1 -0
  138. package/dist/helpers/onedrive.d.ts +5 -0
  139. package/dist/helpers/onedrive.d.ts.map +1 -0
  140. package/dist/helpers/onedrive.js +6 -0
  141. package/dist/helpers/onedrive.js.map +1 -0
  142. package/dist/helpers/pipedrive.d.ts +5 -0
  143. package/dist/helpers/pipedrive.d.ts.map +1 -0
  144. package/dist/helpers/pipedrive.js +6 -0
  145. package/dist/helpers/pipedrive.js.map +1 -0
  146. package/dist/helpers/postgres.d.ts +5 -0
  147. package/dist/helpers/postgres.d.ts.map +1 -0
  148. package/dist/helpers/postgres.js +6 -0
  149. package/dist/helpers/postgres.js.map +1 -0
  150. package/dist/helpers/posthog.d.ts +4 -0
  151. package/dist/helpers/posthog.d.ts.map +1 -0
  152. package/dist/helpers/posthog.js +5 -0
  153. package/dist/helpers/posthog.js.map +1 -0
  154. package/dist/helpers/providers.d.ts +252 -0
  155. package/dist/helpers/providers.d.ts.map +1 -0
  156. package/dist/helpers/providers.js +305 -0
  157. package/dist/helpers/providers.js.map +1 -0
  158. package/dist/helpers/ramp.d.ts +7 -0
  159. package/dist/helpers/ramp.d.ts.map +1 -0
  160. package/dist/helpers/ramp.js +7 -0
  161. package/dist/helpers/ramp.js.map +1 -0
  162. package/dist/helpers/recall.d.ts +5 -0
  163. package/dist/helpers/recall.d.ts.map +1 -0
  164. package/dist/helpers/recall.js +6 -0
  165. package/dist/helpers/recall.js.map +1 -0
  166. package/dist/helpers/reddit.d.ts +5 -0
  167. package/dist/helpers/reddit.d.ts.map +1 -0
  168. package/dist/helpers/reddit.js +6 -0
  169. package/dist/helpers/reddit.js.map +1 -0
  170. package/dist/helpers/redis.d.ts +5 -0
  171. package/dist/helpers/redis.d.ts.map +1 -0
  172. package/dist/helpers/redis.js +6 -0
  173. package/dist/helpers/redis.js.map +1 -0
  174. package/dist/helpers/s3.d.ts +5 -0
  175. package/dist/helpers/s3.d.ts.map +1 -0
  176. package/dist/helpers/s3.js +6 -0
  177. package/dist/helpers/s3.js.map +1 -0
  178. package/dist/helpers/salesforce.d.ts +5 -0
  179. package/dist/helpers/salesforce.d.ts.map +1 -0
  180. package/dist/helpers/salesforce.js +6 -0
  181. package/dist/helpers/salesforce.js.map +1 -0
  182. package/dist/helpers/segment.d.ts +4 -0
  183. package/dist/helpers/segment.d.ts.map +1 -0
  184. package/dist/helpers/segment.js +5 -0
  185. package/dist/helpers/segment.js.map +1 -0
  186. package/dist/helpers/sendgrid.d.ts +5 -0
  187. package/dist/helpers/sendgrid.d.ts.map +1 -0
  188. package/dist/helpers/sendgrid.js +6 -0
  189. package/dist/helpers/sendgrid.js.map +1 -0
  190. package/dist/helpers/sharepoint.d.ts +5 -0
  191. package/dist/helpers/sharepoint.d.ts.map +1 -0
  192. package/dist/helpers/sharepoint.js +6 -0
  193. package/dist/helpers/sharepoint.js.map +1 -0
  194. package/dist/helpers/shopify.d.ts +4 -0
  195. package/dist/helpers/shopify.d.ts.map +1 -0
  196. package/dist/helpers/shopify.js +5 -0
  197. package/dist/helpers/shopify.js.map +1 -0
  198. package/dist/helpers/shortcut.d.ts +5 -0
  199. package/dist/helpers/shortcut.d.ts.map +1 -0
  200. package/dist/helpers/shortcut.js +6 -0
  201. package/dist/helpers/shortcut.js.map +1 -0
  202. package/dist/helpers/slack.d.ts +17 -0
  203. package/dist/helpers/slack.d.ts.map +1 -0
  204. package/dist/helpers/slack.js +4 -0
  205. package/dist/helpers/slack.js.map +1 -0
  206. package/dist/helpers/stripe.d.ts +5 -0
  207. package/dist/helpers/stripe.d.ts.map +1 -0
  208. package/dist/helpers/stripe.js +6 -0
  209. package/dist/helpers/stripe.js.map +1 -0
  210. package/dist/helpers/teams.d.ts +5 -0
  211. package/dist/helpers/teams.d.ts.map +1 -0
  212. package/dist/helpers/teams.js +6 -0
  213. package/dist/helpers/teams.js.map +1 -0
  214. package/dist/helpers/telegram.d.ts +5 -0
  215. package/dist/helpers/telegram.d.ts.map +1 -0
  216. package/dist/helpers/telegram.js +6 -0
  217. package/dist/helpers/telegram.js.map +1 -0
  218. package/dist/helpers/webhook-server.d.ts +4 -0
  219. package/dist/helpers/webhook-server.d.ts.map +1 -0
  220. package/dist/helpers/webhook-server.js +5 -0
  221. package/dist/helpers/webhook-server.js.map +1 -0
  222. package/dist/helpers/x.d.ts +4 -0
  223. package/dist/helpers/x.d.ts.map +1 -0
  224. package/dist/helpers/x.js +5 -0
  225. package/dist/helpers/x.js.map +1 -0
  226. package/dist/helpers/zendesk.d.ts +5 -0
  227. package/dist/helpers/zendesk.d.ts.map +1 -0
  228. package/dist/helpers/zendesk.js +6 -0
  229. package/dist/helpers/zendesk.js.map +1 -0
  230. package/dist/index.d.ts +11 -4
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +3 -0
  233. package/dist/index.js.map +1 -1
  234. package/dist/memory.d.ts +19 -0
  235. package/dist/memory.d.ts.map +1 -0
  236. package/dist/memory.js +2 -0
  237. package/dist/memory.js.map +1 -0
  238. package/dist/plugin-contract.d.ts +5 -0
  239. package/dist/plugin-contract.d.ts.map +1 -0
  240. package/dist/plugin-contract.js +2 -0
  241. package/dist/plugin-contract.js.map +1 -0
  242. package/dist/provider-trigger.d.ts +13 -0
  243. package/dist/provider-trigger.d.ts.map +1 -0
  244. package/dist/provider-trigger.js +18 -0
  245. package/dist/provider-trigger.js.map +1 -0
  246. package/dist/runtime.d.ts +6 -1
  247. package/dist/runtime.d.ts.map +1 -1
  248. package/dist/runtime.js +5 -0
  249. package/dist/runtime.js.map +1 -1
  250. package/dist/slack.d.ts +34 -0
  251. package/dist/slack.d.ts.map +1 -0
  252. package/dist/slack.js +17 -0
  253. package/dist/slack.js.map +1 -0
  254. package/dist/step.d.ts +43 -1
  255. package/dist/step.d.ts.map +1 -1
  256. package/dist/triggers/github.d.ts +8 -0
  257. package/dist/triggers/github.d.ts.map +1 -0
  258. package/dist/triggers/github.js +17 -0
  259. package/dist/triggers/github.js.map +1 -0
  260. package/dist/triggers/index.d.ts +8 -0
  261. package/dist/triggers/index.d.ts.map +1 -0
  262. package/dist/triggers/index.js +9 -0
  263. package/dist/triggers/index.js.map +1 -0
  264. package/dist/triggers/slack.d.ts +8 -0
  265. package/dist/triggers/slack.d.ts.map +1 -0
  266. package/dist/triggers/slack.js +17 -0
  267. package/dist/triggers/slack.js.map +1 -0
  268. package/dist/triggers.d.ts +15 -0
  269. package/dist/triggers.d.ts.map +1 -0
  270. package/dist/triggers.js +43 -0
  271. package/dist/triggers.js.map +1 -0
  272. package/package.json +21 -2
  273. package/src/completion.ts +3 -0
  274. package/src/context.ts +28 -4
  275. package/src/effect-transport.ts +59 -0
  276. package/src/flow.ts +77 -15
  277. package/src/helper-clients.ts +30 -0
  278. package/src/helpers/README.md +42 -0
  279. package/src/helpers/airtable.ts +9 -0
  280. package/src/helpers/asana.ts +10 -0
  281. package/src/helpers/azure-blob.ts +10 -0
  282. package/src/helpers/box.ts +10 -0
  283. package/src/helpers/calendly.ts +10 -0
  284. package/src/helpers/clickup.ts +10 -0
  285. package/src/helpers/clients.ts +48 -0
  286. package/src/helpers/cloudflare.ts +10 -0
  287. package/src/helpers/confluence.ts +10 -0
  288. package/src/helpers/daytona.ts +10 -0
  289. package/src/helpers/docker-hub.ts +9 -0
  290. package/src/helpers/dropbox.ts +10 -0
  291. package/src/helpers/fathom.ts +9 -0
  292. package/src/helpers/gcp.ts +9 -0
  293. package/src/helpers/gcs.ts +10 -0
  294. package/src/helpers/github.ts +10 -0
  295. package/src/helpers/gitlab.ts +10 -0
  296. package/src/helpers/gmail.ts +10 -0
  297. package/src/helpers/google-calendar.ts +10 -0
  298. package/src/helpers/google-drive.ts +10 -0
  299. package/src/helpers/granola.ts +10 -0
  300. package/src/helpers/hubspot.ts +10 -0
  301. package/src/helpers/index.ts +212 -0
  302. package/src/helpers/intercom.ts +10 -0
  303. package/src/helpers/jira.ts +10 -0
  304. package/src/helpers/linear.ts +10 -0
  305. package/src/helpers/mailgun.ts +10 -0
  306. package/src/helpers/mixpanel.ts +10 -0
  307. package/src/helpers/neon.ts +9 -0
  308. package/src/helpers/notion.ts +10 -0
  309. package/src/helpers/onedrive.ts +10 -0
  310. package/src/helpers/pipedrive.ts +10 -0
  311. package/src/helpers/postgres.ts +10 -0
  312. package/src/helpers/posthog.ts +9 -0
  313. package/src/helpers/providers.ts +305 -0
  314. package/src/helpers/ramp.ts +12 -0
  315. package/src/helpers/recall.ts +10 -0
  316. package/src/helpers/reddit.ts +10 -0
  317. package/src/helpers/redis.ts +10 -0
  318. package/src/helpers/s3.ts +10 -0
  319. package/src/helpers/salesforce.ts +10 -0
  320. package/src/helpers/segment.ts +9 -0
  321. package/src/helpers/sendgrid.ts +10 -0
  322. package/src/helpers/sharepoint.ts +10 -0
  323. package/src/helpers/shopify.ts +9 -0
  324. package/src/helpers/shortcut.ts +10 -0
  325. package/src/helpers/slack.ts +16 -0
  326. package/src/helpers/stripe.ts +10 -0
  327. package/src/helpers/teams.ts +10 -0
  328. package/src/helpers/telegram.ts +10 -0
  329. package/src/helpers/webhook-server.ts +9 -0
  330. package/src/helpers/x.ts +9 -0
  331. package/src/helpers/zendesk.ts +10 -0
  332. package/src/index.ts +26 -2
  333. package/src/memory.ts +20 -0
  334. package/src/plugin-contract.ts +5 -0
  335. package/src/provider-trigger.ts +26 -0
  336. package/src/runtime.ts +8 -0
  337. package/src/slack.ts +47 -0
  338. package/src/step.ts +52 -1
  339. package/src/triggers/README.md +75 -0
  340. package/src/triggers/github.ts +19 -0
  341. package/src/triggers/index.ts +10 -0
  342. package/src/triggers/slack.ts +19 -0
  343. package/src/triggers.ts +49 -0
@@ -0,0 +1,26 @@
1
+ import { webhook, type TriggerSource, type WebhookFilter } from "./triggers.js";
2
+
3
+ /** A provider inbox subscription over an envelope's type and payload. */
4
+ export interface ProviderTriggerSource<Provider extends string, Event extends string> extends TriggerSource {
5
+ readonly name: Provider;
6
+ readonly filter: WebhookFilter & { readonly provider: Provider; readonly type: Event };
7
+ }
8
+
9
+ /** Shared implementation for generated provider declarations. */
10
+ export function providerTrigger<P extends string, E extends string>(
11
+ provider: P, event: E, payload?: WebhookFilter,
12
+ ): ProviderTriggerSource<P, E> {
13
+ if (typeof event !== "string" || event.length === 0) throw new TypeError("provider event type must not be empty");
14
+ // Validate separately so an invalid payload cannot become a scalar filter leaf.
15
+ const filter = webhook(provider, payload).filter;
16
+ return webhook(provider, {
17
+ provider, type: event, ...(filter === undefined ? {} : { payload: filter }),
18
+ }) as ProviderTriggerSource<P, E>;
19
+ }
20
+
21
+ export function triggerArgument(value: string, name: string): string {
22
+ if (typeof value !== "string" || value.trim().length === 0) {
23
+ throw new TypeError(`${name} must be a nonempty string`);
24
+ }
25
+ return value;
26
+ }
package/src/runtime.ts CHANGED
@@ -3,5 +3,13 @@ export {
3
3
  type AuthoredFlowDefinition,
4
4
  type FlowBody,
5
5
  type FlowHandle,
6
+ type TriggerHandler,
7
+ type TriggeredFlowHandle,
6
8
  type ReadonlyFlowHeader,
7
9
  } from "./flow.js";
10
+ export { slackPostBody } from "./slack.js";
11
+
12
+ export { createHelpers } from "./helpers/index.js";
13
+ export { helperProviders } from "./helpers/providers.js";
14
+ export { helperClients } from "./helpers/clients.js";
15
+ export { invokeHelper, type HelperCall } from "./effect-transport.js";
package/src/slack.ts ADDED
@@ -0,0 +1,47 @@
1
+ import type { Step } from "./step.js";
2
+ import type { SlackAttachment, SlackBlock } from "./helpers/slack.js";
3
+
4
+ export type { SlackAttachment, SlackBlock } from "./helpers/slack.js";
5
+
6
+ /** Structured message content. Text supplies the notification/accessibility fallback. */
7
+ export interface SlackPostMessage {
8
+ text?: string;
9
+ blocks?: SlackBlock[];
10
+ attachments?: SlackAttachment[];
11
+ }
12
+
13
+ export interface SlackPostOptions extends Omit<SlackPostMessage, "text"> {
14
+ replyTo?: string;
15
+ }
16
+
17
+ export interface SlackReceipt {
18
+ channel: string;
19
+ ts: string;
20
+ ref: string;
21
+ }
22
+
23
+ /** Slack writeback helpers; every call is a journal-backed effect. */
24
+ export interface SlackHelper {
25
+ post(channel: string, text: string | SlackPostMessage, opts?: SlackPostOptions): Step<SlackReceipt>;
26
+ dm(user: string, text: string): Step<{ user: string; ts: string }>;
27
+ reply(channel: string, threadTs: string, text: string): Step<SlackReceipt>;
28
+ react(channel: string, messageTs: string, emoji: string): Step<void>;
29
+ }
30
+
31
+ /** Normalize both authoring forms to the adapter's JSON writeback body. */
32
+ export function slackPostBody(text: string | SlackPostMessage, opts?: SlackPostOptions): SlackPostMessage & { parentRef?: string } {
33
+ const message = typeof text === "string" ? { text } : text;
34
+ const blocks = opts?.blocks ?? message.blocks;
35
+ const attachments = opts?.attachments ?? message.attachments;
36
+ return {
37
+ ...(message.text === undefined ? {} : { text: message.text }),
38
+ ...(blocks === undefined ? {} : { blocks }),
39
+ ...(attachments === undefined ? {} : { attachments }),
40
+ ...(opts?.replyTo ? { parentRef: opts.replyTo } : {}),
41
+ };
42
+ }
43
+
44
+ /** Stable across attempts; deliberately independent of process-tick ordinals. */
45
+ export function flowRunWritebackIdempotency(runId: string, stepId: string): string {
46
+ return `${runId}:${stepId}`;
47
+ }
package/src/step.ts CHANGED
@@ -1,5 +1,56 @@
1
1
  /** A journal-backed step result with its postfix verification gate. */
2
2
  export interface Step<T> extends PromiseLike<T> {
3
- /** Fail the step with `verification_failed` when the predicate is false. */
3
+ /**
4
+ * Attach a named data gate to this step's `verification:` field. The gate is
5
+ * lowered by the SDK into a slice-P journal-honest check that survives
6
+ * replay — its shape is data, not code, so covenant 1 (journal-as-truth)
7
+ * holds. See `packages/sdk/src/named-gates.ts` for the enforcement.
8
+ */
9
+ gate(config: NamedGate): Step<T>;
10
+ /**
11
+ * Predicate gates cannot be journaled — the JavaScript closure would not
12
+ * survive replay — so the executor refuses this branch with
13
+ * `unsupported_gate`. Use a `NamedGate` config-object gate above, or the
14
+ * declarative `verification:` field on the compiled step spec, when you
15
+ * need journal-honest verification.
16
+ */
4
17
  gate(predicate: (value: T) => boolean, because?: string): Step<T>;
5
18
  }
19
+
20
+ /**
21
+ * Slice-P named data gates the authored surface can attach postfix via
22
+ * `.gate(config)`. The SDK's named-gate lowering enforces these exactly (see
23
+ * `packages/sdk/src/named-gates.ts`); the shapes here are the surface-visible
24
+ * subset kept in sync with `NamedDataGate` in the SDK spec.
25
+ */
26
+ export type NamedGate =
27
+ | ReferencesInputNamedGate
28
+ | SubprocessNamedGate
29
+ | WordCountBoundsNamedGate
30
+ | RegexMatchNamedGate;
31
+
32
+ export interface ReferencesInputNamedGate {
33
+ type: 'references_input';
34
+ input_key: string;
35
+ in_output_at?: Array<string | number>;
36
+ }
37
+
38
+ export interface SubprocessNamedGate {
39
+ type: 'subprocess_gate';
40
+ command: string;
41
+ from_output?: Array<string | number>;
42
+ }
43
+
44
+ export interface WordCountBoundsNamedGate {
45
+ type: 'word_count_bounds';
46
+ min?: number;
47
+ max?: number;
48
+ }
49
+
50
+ export interface RegexMatchNamedGate {
51
+ type: 'regex_match';
52
+ pattern: string;
53
+ /** Only i, m, and s; evaluated by a non-backtracking RE2 engine. */
54
+ flags?: string;
55
+ in_output_at?: Array<string | number>;
56
+ }
@@ -0,0 +1,75 @@
1
+ # Provider event triggers
2
+
3
+ ```ts
4
+ import { flow, slack, github } from '@relayflows/surface';
5
+
6
+ export default flow('triage')
7
+ .on(slack.mention('C123'), async (f, event) => { f.done('success'); })
8
+ .on(slack.reaction('eyes'), async (f, event) => { f.done('success'); })
9
+ .on(github.pull_request('opened'), async (f, event) => { f.done('success'); });
10
+ ```
11
+
12
+ Provider namespaces also export from `@relayflows/surface/triggers` and
13
+ `@relayflows/surface/triggers/slack` (or `/github`). Declarations are immutable
14
+ webhook sources: their executor/inbox name is the provider, and their filter
15
+ matches the provider, event type, and requested payload fields. Register those
16
+ provider names in `flows.json`'s `executors` array for preflight.
17
+
18
+ `slack.mention(channel)` subscribes to Slack's `app_mention` event;
19
+ `slack.reaction(emoji)` subscribes to `reaction_added`. Arguments match provider
20
+ values exactly: use the channel ID and reaction name from the incoming event.
21
+ `github.pull_request(action)` filters `payload.action`; omitting the action
22
+ accepts every pull request event. Upstream mappings do not declare action enums,
23
+ so the action parameter is a string. Other generated methods accept an optional
24
+ recursive payload filter, for example `github.push({ ref: 'refs/heads/main' })`.
25
+
26
+ The receiver accepts `POST /providers/slack` with this JSON:
27
+
28
+ ```json
29
+ {"type":"app_mention","payload":{"channel":"C123","text":"Please review"}}
30
+ ```
31
+
32
+ It writes `{ "provider": "slack", "type": "app_mention", "payload": {...} }`
33
+ atomically to `inbox/slack/<id>.json`. The path supplies the provider; a conflicting
34
+ provider in the body or unknown event type is rejected. `payload` is the provider
35
+ event body (Slack's inner `event` object). The event names are the exact mapping
36
+ keys; dots and hyphens become underscores only in TypeScript method names.
37
+ Ingress expects this envelope, not a raw vendor HTTP delivery. Signature
38
+ verification and public ingress remain part of the deployment work tracked in
39
+ #301. Generic `POST /<name>` retains its existing arbitrary-JSON contract.
40
+
41
+ The SDK's `webhookTriggerSpec(id, source)` lowers a declaration to `TriggerSpec`
42
+ for `compileSpec`/`toKernelSpec`. Provision the resulting RunSpec in
43
+ `triggers/<provider>.json`, with executable steps, as in the existing webhook
44
+ executor. The watcher applies the generated filters, journals matching events,
45
+ deduplicates by inbox file ID, and archives consumed events. For example:
46
+
47
+ ```ts
48
+ import { compileSpec, toKernelSpec, webhookTriggerSpec } from '@relayflows/sdk';
49
+ import { slack } from '@relayflows/surface';
50
+
51
+ const binding = toKernelSpec(compileSpec({
52
+ version: '0.1.0', name: 'mentions',
53
+ triggers: [webhookTriggerSpec('mention', slack.mention('C123'))],
54
+ steps: [{ id: 'ack', type: 'deterministic', command: 'printf accepted' }],
55
+ })); // Write binding as JSON to triggers/slack.json before ingress starts.
56
+ ```
57
+
58
+ Each provider inbox still binds one RunSpec. This extends E's declaration and
59
+ inbox contract; deploying TypeScript handler bodies remains the separate #301
60
+ binding step.
61
+
62
+ Generation requires the SDK's development dependencies. The default input is
63
+ the mapping YAML shipped in the pinned `@relayfile/adapter-core` dependency
64
+ (currently Slack and GitHub). A checkout supplies additional providers:
65
+
66
+ ```sh
67
+ node scripts/generate-triggers.mjs
68
+ node scripts/generate-triggers.mjs --check
69
+ node scripts/generate-triggers.mjs --adapters-dir /path/to/relayfile-adapters
70
+ ```
71
+
72
+ The generator reads `packages/core/mappings/*.mapping.yaml`, then each adapter's
73
+ `packages/<adapter>/*.mapping.yaml`; adapter-local mappings take precedence.
74
+ Only adapters with a nonempty `webhooks:` section produce modules. It never
75
+ imports or executes adapter code. Rebuild the surface and SDK after regeneration.
@@ -0,0 +1,19 @@
1
+ // GENERATED by scripts/generate-triggers.mjs — do not edit.
2
+
3
+ import { providerTrigger, triggerArgument } from "../provider-trigger.js";
4
+ import type { WebhookFilter } from "../triggers.js";
5
+
6
+ export const github = Object.freeze({
7
+ issues(filter?: WebhookFilter) {
8
+ return providerTrigger("github", "issues", filter);
9
+ },
10
+ pull_request(action?: string) {
11
+ return providerTrigger("github", "pull_request", action === undefined ? undefined : { action: triggerArgument(action, "action") });
12
+ },
13
+ pull_request_review(filter?: WebhookFilter) {
14
+ return providerTrigger("github", "pull_request_review", filter);
15
+ },
16
+ push(filter?: WebhookFilter) {
17
+ return providerTrigger("github", "push", filter);
18
+ },
19
+ });
@@ -0,0 +1,10 @@
1
+ // GENERATED by scripts/generate-triggers.mjs — do not edit.
2
+
3
+ export { github } from "./github.js";
4
+ export { slack } from "./slack.js";
5
+
6
+ /** Exact upstream event names, plus the generated Slack mention shorthand. */
7
+ export const providerEventTypes = Object.freeze({
8
+ "github": Object.freeze(["issues","pull_request","pull_request_review","push"] as const),
9
+ "slack": Object.freeze(["app_mention","message","reaction_added"] as const),
10
+ });
@@ -0,0 +1,19 @@
1
+ // GENERATED by scripts/generate-triggers.mjs — do not edit.
2
+
3
+ import { providerTrigger, triggerArgument } from "../provider-trigger.js";
4
+ import type { WebhookFilter } from "../triggers.js";
5
+
6
+ export const slack = Object.freeze({
7
+ message(filter?: WebhookFilter) {
8
+ return providerTrigger("slack", "message", filter);
9
+ },
10
+ reaction_added(filter?: WebhookFilter) {
11
+ return providerTrigger("slack", "reaction_added", filter);
12
+ },
13
+ mention(channel: string) {
14
+ return providerTrigger("slack", "app_mention", { channel: triggerArgument(channel, "channel") });
15
+ },
16
+ reaction(emoji: string) {
17
+ return providerTrigger("slack", "reaction_added", { reaction: triggerArgument(emoji, "emoji") });
18
+ },
19
+ });
@@ -0,0 +1,49 @@
1
+ export type WebhookValue = null | boolean | number | string
2
+ | readonly WebhookValue[] | { readonly [key: string]: WebhookValue };
3
+
4
+ /** Recursive object subset; array and scalar leaves match exactly. */
5
+ export type WebhookFilter = { readonly [key: string]: WebhookValue };
6
+
7
+ export interface TriggerSource {
8
+ readonly kind: "webhook";
9
+ readonly name: string;
10
+ readonly filter?: WebhookFilter;
11
+ }
12
+
13
+ /** Plain, immutable data. Constructing a source opens no receiver. */
14
+ export function webhook(name: string, filter?: WebhookFilter): TriggerSource {
15
+ if (typeof name !== "string" || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(name)) {
16
+ throw new TypeError("webhook name must be 1-128 letters, digits, underscores or hyphens, starting with a letter or digit");
17
+ }
18
+ if (filter === undefined) return Object.freeze({ kind: "webhook", name });
19
+ if (filter === null || typeof filter !== "object" || Array.isArray(filter)) {
20
+ throw new TypeError("webhook filter must be a JSON object");
21
+ }
22
+ return Object.freeze({ kind: "webhook", name, filter: snapshot(filter) as WebhookFilter });
23
+ }
24
+
25
+ function snapshot(value: unknown, ancestors = new Set<object>()): WebhookValue {
26
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
27
+ if (typeof value === "number" && Number.isFinite(value)) return value;
28
+ if (typeof value !== "object" || value === null || ancestors.has(value)) {
29
+ throw new TypeError("webhook filter must contain finite, acyclic JSON data");
30
+ }
31
+ const array = Array.isArray(value);
32
+ if (!array && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
33
+ throw new TypeError("webhook filter must contain plain JSON objects");
34
+ }
35
+ ancestors.add(value);
36
+ const entries: [string, WebhookValue][] = [];
37
+ for (const key of Reflect.ownKeys(value)) {
38
+ if (array && key === "length") continue;
39
+ const descriptor = Object.getOwnPropertyDescriptor(value, key)!;
40
+ if (typeof key !== "string" || !descriptor.enumerable || !("value" in descriptor)) {
41
+ throw new TypeError("webhook filter must contain JSON data properties");
42
+ }
43
+ if (array && !/^(0|[1-9][0-9]*)$/.test(key)) throw new TypeError("invalid JSON array property");
44
+ entries.push([key, snapshot(descriptor.value, ancestors)]);
45
+ }
46
+ ancestors.delete(value);
47
+ if (array && entries.length !== value.length) throw new TypeError("webhook filter arrays must not be sparse");
48
+ return Object.freeze(array ? entries.map(([, item]) => item) : Object.fromEntries(entries));
49
+ }