@oomol-lab/open-connector 1.6.5 → 1.8.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 (495) hide show
  1. package/README.md +4 -0
  2. package/assets/open-connector/catalog/apps/airtable.json +134 -0
  3. package/assets/open-connector/catalog/apps/aisa.json +6985 -319
  4. package/assets/open-connector/catalog/apps/baizhi_mcp.json +135 -0
  5. package/assets/open-connector/catalog/apps/cal.json +24 -6
  6. package/assets/open-connector/catalog/apps/discordbot.json +2888 -248
  7. package/assets/open-connector/catalog/apps/drawio_mcp.json +192 -0
  8. package/assets/open-connector/catalog/apps/enormail.json +411 -0
  9. package/assets/open-connector/catalog/apps/feishu_app_bot.json +158 -0
  10. package/assets/open-connector/catalog/apps/firecrawl.json +176 -32
  11. package/assets/open-connector/catalog/apps/framejet.json +273 -0
  12. package/assets/open-connector/catalog/apps/futunn.json +2967 -0
  13. package/assets/open-connector/catalog/apps/github.json +275 -0
  14. package/assets/open-connector/catalog/apps/gitlab.json +125 -0
  15. package/assets/open-connector/catalog/apps/gmail.json +376 -0
  16. package/assets/open-connector/catalog/apps/google_analytics.json +4 -1
  17. package/assets/open-connector/catalog/apps/google_bigquery.json +4 -1
  18. package/assets/open-connector/catalog/apps/google_search_console.json +4 -1
  19. package/assets/open-connector/catalog/apps/googlecalendar.json +210 -1
  20. package/assets/open-connector/catalog/apps/googlechat.json +694 -7
  21. package/assets/open-connector/catalog/apps/googledocs.json +4 -1
  22. package/assets/open-connector/catalog/apps/googledrive.json +479 -0
  23. package/assets/open-connector/catalog/apps/googlesheets.json +148 -1
  24. package/assets/open-connector/catalog/apps/granola.json +23 -0
  25. package/assets/open-connector/catalog/apps/hithink_finance.json +6 -3
  26. package/assets/open-connector/catalog/apps/indexed.json +1115 -0
  27. package/assets/open-connector/catalog/apps/keepa.json +3534 -987
  28. package/assets/open-connector/catalog/apps/linear.json +133 -0
  29. package/assets/open-connector/catalog/apps/linear_mcp.json +510 -0
  30. package/assets/open-connector/catalog/apps/moneyforward_mcp.json +1432 -0
  31. package/assets/open-connector/catalog/apps/notion.json +588 -1
  32. package/assets/open-connector/catalog/apps/notion_mcp.json +490 -0
  33. package/assets/open-connector/catalog/apps/odoo.json +619 -0
  34. package/assets/open-connector/catalog/apps/one_drive.json +185 -0
  35. package/assets/open-connector/catalog/apps/outlook.json +212 -8
  36. package/assets/open-connector/catalog/apps/outlook_calendar.json +23 -2
  37. package/assets/open-connector/catalog/apps/postiz.json +334 -0
  38. package/assets/open-connector/catalog/apps/proworkflow.json +529 -0
  39. package/assets/open-connector/catalog/apps/sellersprite_mcp.json +2 -1
  40. package/assets/open-connector/catalog/apps/shopify.json +282 -0
  41. package/assets/open-connector/catalog/apps/slack.json +405 -0
  42. package/assets/open-connector/catalog/apps/slackbot.json +214 -0
  43. package/assets/open-connector/catalog/apps/spotify.json +46 -43
  44. package/assets/open-connector/catalog/apps/stripe.json +96 -0
  45. package/assets/open-connector/catalog/apps/telegram.json +138 -0
  46. package/assets/open-connector/catalog/apps/tencent_docs.json +3 -0
  47. package/assets/open-connector/catalog/apps/weixin_store.json +543 -2
  48. package/assets/open-connector/catalog/apps/wisburg.json +1528 -0
  49. package/assets/open-connector/catalog/apps/woocommerce.json +127 -0
  50. package/assets/open-connector/catalog/apps/youtube.json +4 -1
  51. package/assets/open-connector/catalog/apps/zendesk.json +152 -0
  52. package/assets/open-connector/catalog/apps/zerotier.json +3319 -0
  53. package/assets/open-connector/catalog/apps-index.json +1 -1
  54. package/assets/open-connector/migrations/0014_saas_project.sql +55 -0
  55. package/assets/open-connector/migrations/0015_saas_cleanup_runtime.sql +8 -0
  56. package/assets/open-connector/migrations/0016_trigger_policy.sql +1 -0
  57. package/assets/open-connector/migrations/0017_trigger_subscriptions.sql +17 -0
  58. package/assets/open-connector/migrations/postgresql/0014_saas_project.sql +55 -0
  59. package/assets/open-connector/migrations/postgresql/0015_saas_cleanup_runtime.sql +8 -0
  60. package/assets/open-connector/migrations/postgresql/0016_trigger_policy.sql +1 -0
  61. package/assets/open-connector/migrations/postgresql/0017_trigger_subscriptions.sql +17 -0
  62. package/package.json +2 -2
  63. package/src/connection-service.d.ts +40 -7
  64. package/src/connection-service.js +60 -18
  65. package/src/core/action-policy.d.ts +8 -1
  66. package/src/core/action-policy.js +51 -0
  67. package/src/core/cast.d.ts +13 -0
  68. package/src/core/cast.js +18 -1
  69. package/src/core/guarded-fetch.d.ts +11 -3
  70. package/src/core/guarded-fetch.js +19 -7
  71. package/src/core/provider-scenarios.js +67 -13
  72. package/src/core/remote-http.d.ts +33 -0
  73. package/src/core/remote-http.js +104 -0
  74. package/src/core/request.d.ts +1 -0
  75. package/src/core/request.js +11 -1
  76. package/src/core/types.d.ts +5 -1
  77. package/src/marketplace/marketplace-service.d.ts +0 -1
  78. package/src/marketplace/marketplace-service.js +80 -92
  79. package/src/mcp.js +26 -9
  80. package/src/oauth/oauth-client-config-service.d.ts +16 -1
  81. package/src/oauth/oauth-client-config-service.js +59 -3
  82. package/src/oauth/oauth-flow-service.d.ts +14 -1
  83. package/src/oauth/oauth-flow-service.js +14 -6
  84. package/src/providers/17track/runtime.js +1 -1
  85. package/src/providers/action-contracts.generated.d.ts +20 -6
  86. package/src/providers/aifinmarket/runtime.js +1 -1
  87. package/src/providers/airtable/executors.d.ts +3 -0
  88. package/src/providers/airtable/executors.js +2 -0
  89. package/src/providers/airtable/trigger-on-record-changed.d.ts +2 -0
  90. package/src/providers/airtable/trigger-on-record-changed.definition.d.ts +4 -0
  91. package/src/providers/airtable/trigger-on-record-changed.definition.js +54 -0
  92. package/src/providers/airtable/trigger-on-record-changed.js +235 -0
  93. package/src/providers/aisa/executors.js +912 -50
  94. package/src/providers/aliyun_ack/runtime.js +1 -1
  95. package/src/providers/aliyun_sls/runtime.js +1 -1
  96. package/src/providers/app_store_server/runtime-helpers.js +1 -1
  97. package/src/providers/baizhi_mcp/actions.d.ts +2 -0
  98. package/src/providers/baizhi_mcp/actions.js +40 -0
  99. package/src/providers/baizhi_mcp/executors.d.ts +3 -0
  100. package/src/providers/baizhi_mcp/executors.js +102 -0
  101. package/src/providers/bazhuayu/runtime.js +2 -2
  102. package/src/providers/bilibili/runtime.js +2 -4
  103. package/src/providers/bilibili/upload.js +9 -7
  104. package/src/providers/cal/actions.js +5 -1
  105. package/src/providers/cloudflare_browser_rendering/executors.js +1 -1
  106. package/src/providers/cloudflare_dns/executors.js +1 -1
  107. package/src/providers/{cloudflare-current-user.js → cloudflare_dns/runtime-user.js} +2 -2
  108. package/src/providers/cloudflare_dns/runtime.d.ts +1 -1
  109. package/src/providers/cloudflare_dns/runtime.js +1 -1
  110. package/src/providers/cloudflare_r2/executors.js +1 -1
  111. package/src/providers/cloudflare_r2/runtime.d.ts +1 -1
  112. package/src/providers/cloudflare_r2/runtime.js +1 -1
  113. package/src/providers/cloudflare_worker/executors.js +1 -1
  114. package/src/providers/cloudflare_worker/runtime.d.ts +1 -1
  115. package/src/providers/cloudflare_worker/runtime.js +1 -1
  116. package/src/providers/dingtalk_mcp/runtime.js +1 -1
  117. package/src/providers/discordbot/executors.d.ts +0 -9
  118. package/src/providers/discordbot/executors.js +9 -101
  119. package/src/providers/discordbot/runtime-guilds.d.ts +3 -0
  120. package/src/providers/discordbot/runtime-guilds.js +464 -0
  121. package/src/providers/discordbot/runtime.d.ts +42 -0
  122. package/src/providers/discordbot/runtime.js +124 -0
  123. package/src/providers/drawio_mcp/executors.d.ts +3 -0
  124. package/src/providers/drawio_mcp/executors.js +19 -0
  125. package/src/providers/drawio_mcp/runtime.d.ts +8 -0
  126. package/src/providers/drawio_mcp/runtime.js +175 -0
  127. package/src/providers/enormail/executors.d.ts +4 -0
  128. package/src/providers/enormail/executors.js +97 -0
  129. package/src/providers/fastmoss_mcp/executors.js +2 -2
  130. package/src/providers/feishu_app_bot/executors.d.ts +3 -0
  131. package/src/providers/feishu_app_bot/executors.js +2 -0
  132. package/src/providers/feishu_app_bot/trigger-config.d.ts +1 -0
  133. package/src/providers/feishu_app_bot/trigger-config.js +10 -0
  134. package/src/providers/feishu_app_bot/trigger-on-event.d.ts +2 -0
  135. package/src/providers/feishu_app_bot/trigger-on-event.definition.d.ts +4 -0
  136. package/src/providers/feishu_app_bot/trigger-on-event.definition.js +63 -0
  137. package/src/providers/feishu_app_bot/trigger-on-event.js +29 -0
  138. package/src/providers/feishu_app_bot/trigger-subscriptions.d.ts +5 -0
  139. package/src/providers/feishu_app_bot/trigger-subscriptions.js +70 -0
  140. package/src/providers/finchina/executors.js +1 -1
  141. package/src/providers/framejet/executors.d.ts +4 -0
  142. package/src/providers/framejet/executors.js +19 -0
  143. package/src/providers/framejet/runtime.d.ts +16 -0
  144. package/src/providers/framejet/runtime.js +148 -0
  145. package/src/providers/futunn/actions.d.ts +2 -0
  146. package/src/providers/futunn/actions.js +152 -0
  147. package/src/providers/futunn/actions.research.d.ts +2 -0
  148. package/src/providers/futunn/actions.research.js +423 -0
  149. package/src/providers/futunn/actions.trading.d.ts +2 -0
  150. package/src/providers/futunn/actions.trading.js +204 -0
  151. package/src/providers/futunn/executors.d.ts +3 -0
  152. package/src/providers/futunn/executors.js +24 -0
  153. package/src/providers/futunn/runtime-research.d.ts +3 -0
  154. package/src/providers/futunn/runtime-research.js +133 -0
  155. package/src/providers/futunn/runtime-trading.d.ts +3 -0
  156. package/src/providers/futunn/runtime-trading.js +39 -0
  157. package/src/providers/futunn/runtime.d.ts +2 -0
  158. package/src/providers/futunn/runtime.js +50 -0
  159. package/src/providers/futunn/transport.d.ts +11 -0
  160. package/src/providers/futunn/transport.js +76 -0
  161. package/src/providers/gildata/executors.js +1 -1
  162. package/src/providers/github/executors.d.ts +3 -0
  163. package/src/providers/github/executors.js +6 -0
  164. package/src/providers/github/trigger-on-repo-event.d.ts +2 -0
  165. package/src/providers/github/trigger-on-repo-event.definition.d.ts +4 -0
  166. package/src/providers/github/trigger-on-repo-event.definition.js +94 -0
  167. package/src/providers/github/trigger-on-repo-event.js +168 -0
  168. package/src/providers/github/trigger-watch-pull-request.d.ts +2 -0
  169. package/src/providers/github/trigger-watch-pull-request.definition.d.ts +4 -0
  170. package/src/providers/github/trigger-watch-pull-request.definition.js +49 -0
  171. package/src/providers/github/trigger-watch-pull-request.js +106 -0
  172. package/src/providers/gitlab/executors.d.ts +3 -0
  173. package/src/providers/gitlab/executors.js +2 -0
  174. package/src/providers/gitlab/trigger-on-project-event.d.ts +2 -0
  175. package/src/providers/gitlab/trigger-on-project-event.definition.d.ts +5 -0
  176. package/src/providers/gitlab/trigger-on-project-event.definition.js +63 -0
  177. package/src/providers/gitlab/trigger-on-project-event.js +186 -0
  178. package/src/providers/gmail/executors.d.ts +3 -0
  179. package/src/providers/gmail/executors.js +5 -3
  180. package/src/providers/gmail/message.d.ts +6 -8
  181. package/src/providers/gmail/message.js +4 -0
  182. package/src/providers/gmail/scopes.d.ts +32 -0
  183. package/src/providers/gmail/scopes.js +37 -0
  184. package/src/providers/gmail/trigger-on-message-received.d.ts +2 -0
  185. package/src/providers/gmail/trigger-on-message-received.definition.d.ts +4 -0
  186. package/src/providers/gmail/trigger-on-message-received.definition.js +74 -0
  187. package/src/providers/gmail/trigger-on-message-received.js +232 -0
  188. package/src/providers/google_analytics/executors.js +2 -2
  189. package/src/providers/google_analytics/scopes.js +6 -1
  190. package/src/providers/google_bigquery/executors.js +2 -2
  191. package/src/providers/google_bigquery/scopes.js +2 -0
  192. package/src/providers/google_search_console/executors.js +2 -2
  193. package/src/providers/google_search_console/scopes.js +2 -0
  194. package/src/providers/googleads/executors.js +1 -1
  195. package/src/providers/googleads/scopes.d.ts +1 -3
  196. package/src/providers/googleads/scopes.js +2 -4
  197. package/src/providers/googlecalendar/executors.d.ts +3 -0
  198. package/src/providers/googlecalendar/executors.js +3 -1
  199. package/src/providers/googlecalendar/runtime-shared.js +2 -2
  200. package/src/providers/googlecalendar/scopes.js +2 -0
  201. package/src/providers/googlecalendar/trigger-on-event-changed.d.ts +2 -0
  202. package/src/providers/googlecalendar/trigger-on-event-changed.definition.d.ts +4 -0
  203. package/src/providers/googlecalendar/trigger-on-event-changed.definition.js +74 -0
  204. package/src/providers/googlecalendar/trigger-on-event-changed.js +233 -0
  205. package/src/providers/googlechat/executors.d.ts +1 -3
  206. package/src/providers/googlechat/executors.js +219 -28
  207. package/src/providers/googlechat/members.d.ts +55 -0
  208. package/src/providers/googlechat/members.js +293 -0
  209. package/src/providers/googlechat/runtime.d.ts +16 -0
  210. package/src/providers/googlechat/runtime.js +25 -0
  211. package/src/providers/googlechat/scopes.d.ts +22 -3
  212. package/src/providers/googlechat/scopes.js +30 -7
  213. package/src/providers/googledocs/executors.js +1 -1
  214. package/src/providers/googledrive/executors.d.ts +3 -0
  215. package/src/providers/googledrive/executors.js +9 -2
  216. package/src/providers/{google-auth.d.ts → googledrive/runtime-auth.d.ts} +2 -2
  217. package/src/providers/{google-auth.js → googledrive/runtime-auth.js} +3 -3
  218. package/src/providers/googledrive/runtime-collaboration.js +1 -1
  219. package/src/providers/{google-runtime.d.ts → googledrive/runtime-request.d.ts} +1 -1
  220. package/src/providers/{google-runtime.js → googledrive/runtime-request.js} +2 -2
  221. package/src/providers/googledrive/trigger-changes.d.ts +12 -0
  222. package/src/providers/googledrive/trigger-changes.definition.d.ts +7 -0
  223. package/src/providers/googledrive/trigger-changes.definition.js +101 -0
  224. package/src/providers/googledrive/trigger-changes.js +452 -0
  225. package/src/providers/googledrive/trigger-on-file-change.d.ts +2 -0
  226. package/src/providers/googledrive/trigger-on-file-change.definition.d.ts +4 -0
  227. package/src/providers/googledrive/trigger-on-file-change.definition.js +77 -0
  228. package/src/providers/googledrive/trigger-on-file-change.js +258 -0
  229. package/src/providers/googleforms/executors.js +2 -2
  230. package/src/providers/googleforms/scopes.d.ts +0 -3
  231. package/src/providers/googleforms/scopes.js +2 -6
  232. package/src/providers/googlemeet/executors.js +2 -2
  233. package/src/providers/googlemeet/scopes.d.ts +0 -3
  234. package/src/providers/googlemeet/scopes.js +2 -6
  235. package/src/providers/googlesheets/executors.d.ts +3 -0
  236. package/src/providers/googlesheets/executors.js +3 -1
  237. package/src/providers/googlesheets/scopes.js +2 -0
  238. package/src/providers/googlesheets/trigger-on-row-added.d.ts +2 -0
  239. package/src/providers/googlesheets/trigger-on-row-added.definition.d.ts +4 -0
  240. package/src/providers/googlesheets/trigger-on-row-added.definition.js +54 -0
  241. package/src/providers/googlesheets/trigger-on-row-added.js +234 -0
  242. package/src/providers/googleslides/executors.js +2 -2
  243. package/src/providers/googleslides/scopes.d.ts +0 -3
  244. package/src/providers/googleslides/scopes.js +2 -6
  245. package/src/providers/googletasks/executors.js +2 -2
  246. package/src/providers/googletasks/scopes.d.ts +0 -3
  247. package/src/providers/googletasks/scopes.js +2 -6
  248. package/src/providers/granola/actions.js +2 -0
  249. package/src/providers/granola/runtime-mcp.js +2 -0
  250. package/src/providers/granola/runtime.js +2 -2
  251. package/src/providers/hithink_finance/runtime.js +1 -1
  252. package/src/providers/indexed/executors.d.ts +4 -0
  253. package/src/providers/indexed/executors.js +16 -0
  254. package/src/providers/indexed/runtime.d.ts +26 -0
  255. package/src/providers/indexed/runtime.js +129 -0
  256. package/src/providers/indiegogo/executors.js +1 -1
  257. package/src/providers/investoday_mcp/executors.js +2 -2
  258. package/src/providers/iyunbiao/runtime.js +2 -2
  259. package/src/providers/keepa/actions.d.ts +1 -1
  260. package/src/providers/keepa/actions.js +371 -149
  261. package/src/providers/keepa/deal-attributes.d.ts +1 -0
  262. package/src/providers/keepa/deal-attributes.js +26 -0
  263. package/src/providers/keepa/runtime.js +212 -18
  264. package/src/providers/kingdee/executors.js +1 -1
  265. package/src/providers/kingdee/runtime.js +2 -2
  266. package/src/providers/kuaidi100/runtime.js +1 -1
  267. package/src/providers/linear/executors.d.ts +3 -0
  268. package/src/providers/linear/executors.js +14 -9
  269. package/src/providers/linear/trigger-on-issue-changed.d.ts +2 -0
  270. package/src/providers/linear/trigger-on-issue-changed.definition.d.ts +5 -0
  271. package/src/providers/linear/trigger-on-issue-changed.definition.js +43 -0
  272. package/src/providers/linear/trigger-on-issue-changed.js +215 -0
  273. package/src/providers/linear_mcp/actions.d.ts +47 -0
  274. package/src/providers/linear_mcp/actions.js +102 -0
  275. package/src/providers/linear_mcp/endpoints.d.ts +3 -0
  276. package/src/providers/linear_mcp/endpoints.js +3 -0
  277. package/src/providers/linear_mcp/executors.d.ts +3 -0
  278. package/src/providers/linear_mcp/executors.js +9 -0
  279. package/src/providers/linear_mcp/runtime-mcp.d.ts +15 -0
  280. package/src/providers/linear_mcp/runtime-mcp.js +238 -0
  281. package/src/providers/lingxing_mcp/runtime.js +1 -1
  282. package/src/providers/mcdonalds_cn_mcp/runtime.js +1 -1
  283. package/src/providers/metabase/mcp-runtime.js +1 -1
  284. package/src/providers/moneyforward_mcp/executors.d.ts +3 -0
  285. package/src/providers/moneyforward_mcp/executors.js +11 -0
  286. package/src/providers/moneyforward_mcp/manifest.d.ts +31 -0
  287. package/src/providers/moneyforward_mcp/manifest.js +204 -0
  288. package/src/providers/moneyforward_mcp/runtime.d.ts +18 -0
  289. package/src/providers/moneyforward_mcp/runtime.js +296 -0
  290. package/src/providers/notion/executors.d.ts +3 -0
  291. package/src/providers/notion/executors.js +41 -3
  292. package/src/providers/notion/trigger-on-database-page-event.d.ts +2 -0
  293. package/src/providers/notion/trigger-on-database-page-event.definition.d.ts +4 -0
  294. package/src/providers/notion/trigger-on-database-page-event.definition.js +63 -0
  295. package/src/providers/notion/trigger-on-database-page-event.js +293 -0
  296. package/src/providers/notion_mcp/endpoints.d.ts +3 -0
  297. package/src/providers/notion_mcp/endpoints.js +3 -0
  298. package/src/providers/notion_mcp/executors.d.ts +3 -0
  299. package/src/providers/notion_mcp/executors.js +176 -0
  300. package/src/providers/notion_mcp/mcp-response.d.ts +86 -0
  301. package/src/providers/notion_mcp/mcp-response.js +314 -0
  302. package/src/providers/odoo/executors.d.ts +3 -0
  303. package/src/providers/odoo/executors.js +32 -0
  304. package/src/providers/odoo/runtime.d.ts +16 -0
  305. package/src/providers/odoo/runtime.js +140 -0
  306. package/src/providers/one_drive/executors.d.ts +3 -0
  307. package/src/providers/one_drive/executors.js +2 -0
  308. package/src/providers/one_drive/trigger-on-item-changed.d.ts +2 -0
  309. package/src/providers/one_drive/trigger-on-item-changed.definition.d.ts +4 -0
  310. package/src/providers/one_drive/trigger-on-item-changed.definition.js +63 -0
  311. package/src/providers/one_drive/trigger-on-item-changed.js +214 -0
  312. package/src/providers/outlook/executors.d.ts +3 -0
  313. package/src/providers/outlook/executors.js +29 -6
  314. package/src/providers/outlook/microsoft-graph.js +17 -6
  315. package/src/providers/outlook/trigger-on-message-received.d.ts +2 -0
  316. package/src/providers/outlook/trigger-on-message-received.definition.d.ts +4 -0
  317. package/src/providers/outlook/trigger-on-message-received.definition.js +93 -0
  318. package/src/providers/outlook/trigger-on-message-received.js +226 -0
  319. package/src/providers/outlook_calendar/executors.js +30 -7
  320. package/src/providers/patsnap_mcp/executors.js +2 -2
  321. package/src/providers/postiz/executors.d.ts +4 -0
  322. package/src/providers/postiz/executors.js +83 -0
  323. package/src/providers/provider-loader.d.ts +5 -0
  324. package/src/providers/provider-loader.js +4 -0
  325. package/src/providers/provider-runtime.d.ts +15 -0
  326. package/src/providers/provider-runtime.js +57 -4
  327. package/src/providers/proworkflow/executors.d.ts +4 -0
  328. package/src/providers/proworkflow/executors.js +135 -0
  329. package/src/providers/registry.generated.js +14 -0
  330. package/src/providers/scrape_creators/catalog.js +1 -1
  331. package/src/providers/scrape_creators/runtime.js +1 -1
  332. package/src/providers/sellersprite_mcp/executors.js +2 -2
  333. package/src/providers/sellersprite_mcp/official-actions.js +3 -2
  334. package/src/providers/sentry/runtime.js +6 -7
  335. package/src/providers/shopify/executors.d.ts +3 -0
  336. package/src/providers/shopify/executors.js +2 -0
  337. package/src/providers/shopify/trigger-on-shop-event.d.ts +2 -0
  338. package/src/providers/shopify/trigger-on-shop-event.definition.d.ts +4 -0
  339. package/src/providers/shopify/trigger-on-shop-event.definition.js +214 -0
  340. package/src/providers/shopify/trigger-on-shop-event.js +165 -0
  341. package/src/providers/slack/actions.js +52 -3
  342. package/src/providers/slack/executors.d.ts +3 -0
  343. package/src/providers/slack/executors.js +2 -0
  344. package/src/providers/slack/runtime.js +58 -21
  345. package/src/providers/slack/trigger-on-message-posted.d.ts +2 -0
  346. package/src/providers/slack/trigger-on-message-posted.definition.d.ts +4 -0
  347. package/src/providers/slack/trigger-on-message-posted.definition.js +80 -0
  348. package/src/providers/slack/trigger-on-message-posted.js +176 -0
  349. package/src/providers/slickdeals/runtime.js +1 -1
  350. package/src/providers/sorftime_mcp/executors.js +2 -2
  351. package/src/providers/spotify/runtime.js +15 -4
  352. package/src/providers/stripe/executors.d.ts +3 -0
  353. package/src/providers/stripe/executors.js +2 -0
  354. package/src/providers/stripe/trigger-on-event.d.ts +2 -0
  355. package/src/providers/stripe/trigger-on-event.definition.d.ts +4 -0
  356. package/src/providers/stripe/trigger-on-event.definition.js +43 -0
  357. package/src/providers/stripe/trigger-on-event.js +212 -0
  358. package/src/providers/telegram/executors.d.ts +3 -0
  359. package/src/providers/telegram/executors.js +2 -0
  360. package/src/providers/telegram/trigger-on-update.d.ts +2 -0
  361. package/src/providers/telegram/trigger-on-update.definition.d.ts +5 -0
  362. package/src/providers/telegram/trigger-on-update.definition.js +78 -0
  363. package/src/providers/telegram/trigger-on-update.js +141 -0
  364. package/src/providers/tikhub/bounded-response.d.ts +1 -1
  365. package/src/providers/tikhub/bounded-response.js +8 -34
  366. package/src/providers/tikhub/endpoint-catalog.js +1 -1
  367. package/src/providers/tikhub/runtime.js +2 -2
  368. package/src/providers/tongdaxin/executors.js +79 -15
  369. package/src/providers/uspto/executors.js +1 -1
  370. package/src/providers/waffo/executors.js +1 -1
  371. package/src/providers/waffo/runtime.js +1 -1
  372. package/src/providers/wecom_mcp/runtime.js +1 -1
  373. package/src/providers/weixin_store/access-token.d.ts +2 -1
  374. package/src/providers/weixin_store/access-token.js +15 -4
  375. package/src/providers/weixin_store/executors.js +97 -12
  376. package/src/providers/wisburg/executors.d.ts +4 -0
  377. package/src/providers/wisburg/executors.js +13 -0
  378. package/src/providers/wisburg/runtime.d.ts +12 -0
  379. package/src/providers/wisburg/runtime.js +133 -0
  380. package/src/providers/woocommerce/executors.d.ts +3 -0
  381. package/src/providers/woocommerce/executors.js +2 -0
  382. package/src/providers/woocommerce/trigger-on-store-event.d.ts +2 -0
  383. package/src/providers/woocommerce/trigger-on-store-event.definition.d.ts +4 -0
  384. package/src/providers/woocommerce/trigger-on-store-event.definition.js +55 -0
  385. package/src/providers/woocommerce/trigger-on-store-event.js +179 -0
  386. package/src/providers/xydc_mcp/executors.js +2 -2
  387. package/src/providers/youtube/executors.js +1 -1
  388. package/src/providers/youtube/runtime.js +1 -1
  389. package/src/providers/zendesk/executors.d.ts +3 -0
  390. package/src/providers/zendesk/executors.js +2 -0
  391. package/src/providers/zendesk/trigger-on-event.d.ts +2 -0
  392. package/src/providers/zendesk/trigger-on-event.definition.d.ts +5 -0
  393. package/src/providers/zendesk/trigger-on-event.definition.js +101 -0
  394. package/src/providers/zendesk/trigger-on-event.js +188 -0
  395. package/src/providers/zerotier/executors.d.ts +9 -0
  396. package/src/providers/zerotier/executors.js +629 -0
  397. package/src/providers/zerotier/runtime.d.ts +54 -0
  398. package/src/providers/zerotier/runtime.js +207 -0
  399. package/src/saas/saas-cleanup-service.d.ts +26 -0
  400. package/src/saas/saas-cleanup-service.js +124 -0
  401. package/src/saas/saas-client.d.ts +86 -0
  402. package/src/saas/saas-client.js +369 -0
  403. package/src/saas/saas-execution-service.d.ts +15 -0
  404. package/src/saas/saas-execution-service.js +21 -0
  405. package/src/saas/saas-oauth-service.d.ts +25 -0
  406. package/src/saas/saas-oauth-service.js +197 -0
  407. package/src/saas/saas-project-service.d.ts +61 -0
  408. package/src/saas/saas-project-service.js +211 -0
  409. package/src/server/actions/action-idempotency.d.ts +1 -0
  410. package/src/server/actions/action-idempotency.js +1 -0
  411. package/src/server/actions/action-runner.d.ts +7 -0
  412. package/src/server/actions/action-runner.js +43 -7
  413. package/src/server/actions/run-log-summary.js +9 -0
  414. package/src/server/api/auth.d.ts +1 -0
  415. package/src/server/api/auth.js +13 -2
  416. package/src/server/api/cache-policy.js +4 -1
  417. package/src/server/api/connection-input.d.ts +7 -1
  418. package/src/server/api/connection-input.js +7 -1
  419. package/src/server/api/connection-routes.d.ts +3 -1
  420. package/src/server/api/connection-routes.js +21 -3
  421. package/src/server/api/http-utils.d.ts +4 -3
  422. package/src/server/api/oauth-completion-page.d.ts +124 -0
  423. package/src/server/api/oauth-completion-page.js +113 -18
  424. package/src/server/api/openapi.js +123 -15
  425. package/src/server/api/policy-input.js +6 -0
  426. package/src/server/api/runtime-api.d.ts +18 -3
  427. package/src/server/api/runtime-api.js +36 -5
  428. package/src/server/api/saas-completion-page.d.ts +2 -0
  429. package/src/server/api/saas-completion-page.js +103 -0
  430. package/src/server/connect-app.d.ts +5 -0
  431. package/src/server/connect-app.js +50 -0
  432. package/src/server/connect-server.d.ts +12 -0
  433. package/src/server/connect-server.js +157 -15
  434. package/src/server/connector-runtime.d.ts +3 -1
  435. package/src/server/connector-runtime.js +5 -2
  436. package/src/server/files/transit-files.js +16 -7
  437. package/src/server/proxy/proxy-runner.d.ts +5 -1
  438. package/src/server/proxy/proxy-runner.js +72 -26
  439. package/src/server/storage/connection-request-store.d.ts +41 -1
  440. package/src/server/storage/connection-request-store.js +245 -20
  441. package/src/server/storage/connection-store.d.ts +16 -0
  442. package/src/server/storage/connection-store.js +119 -0
  443. package/src/server/storage/node-runtime-database.js +3 -3
  444. package/src/server/storage/{postgres-migrations.d.ts → postgres/migrations.d.ts} +2 -2
  445. package/src/server/storage/{postgres-migrations.js → postgres/migrations.js} +1 -1
  446. package/src/server/storage/postgres/runtime-store.d.ts +43 -0
  447. package/src/server/storage/{postgres-runtime-store.js → postgres/runtime-store.js} +59 -94
  448. package/src/server/storage/runtime-database.d.ts +4 -0
  449. package/src/server/storage/runtime-sql.d.ts +1 -1
  450. package/src/server/storage/runtime-sql.js +2 -1
  451. package/src/server/storage/runtime-store.d.ts +1 -0
  452. package/src/server/storage/runtime-token-service.d.ts +2 -0
  453. package/src/server/storage/runtime-token-service.js +3 -0
  454. package/src/server/storage/saas-project-store.d.ts +77 -0
  455. package/src/server/storage/saas-project-store.js +273 -0
  456. package/src/server/storage/{sqlite-runtime-store.d.ts → sqlite/runtime-store.d.ts} +21 -25
  457. package/src/server/storage/{sqlite-runtime-store.js → sqlite/runtime-store.js} +100 -115
  458. package/src/server/storage/trigger-store.d.ts +16 -0
  459. package/src/server/storage/trigger-store.js +96 -0
  460. package/src/triggers/common/config.d.ts +2 -0
  461. package/src/triggers/common/config.js +17 -0
  462. package/src/triggers/common/configOptions.d.ts +13 -0
  463. package/src/triggers/common/configOptions.js +1 -0
  464. package/src/triggers/common/encoding.d.ts +3 -0
  465. package/src/triggers/common/encoding.js +19 -0
  466. package/src/triggers/common/integration.d.ts +115 -0
  467. package/src/triggers/common/integration.js +31 -0
  468. package/src/triggers/common/json.d.ts +6 -0
  469. package/src/triggers/common/json.js +91 -0
  470. package/src/triggers/common/poll.d.ts +41 -0
  471. package/src/triggers/common/poll.js +15 -0
  472. package/src/triggers/common/proxy.d.ts +14 -0
  473. package/src/triggers/common/proxy.js +1 -0
  474. package/src/triggers/common/types.d.ts +42 -0
  475. package/src/triggers/common/types.js +1 -0
  476. package/src/triggers/maintenance.d.ts +40 -0
  477. package/src/triggers/maintenance.js +120 -0
  478. package/src/triggers/metadata.d.ts +8 -0
  479. package/src/triggers/metadata.js +1 -0
  480. package/src/triggers/request.d.ts +33 -0
  481. package/src/triggers/request.js +52 -0
  482. package/src/triggers/resources.d.ts +12 -0
  483. package/src/triggers/resources.js +121 -0
  484. package/src/triggers/signature.d.ts +4 -0
  485. package/src/triggers/signature.js +48 -0
  486. package/src/triggers/store.d.ts +29 -0
  487. package/src/triggers/store.js +1 -0
  488. package/src/triggers/subscriptions.d.ts +22 -0
  489. package/src/triggers/subscriptions.js +220 -0
  490. package/src/triggers/trigger-runner.d.ts +34 -0
  491. package/src/triggers/trigger-runner.js +169 -0
  492. package/src/providers/sentry/scopes.d.ts +0 -1
  493. package/src/providers/sentry/scopes.js +0 -7
  494. package/src/server/storage/postgres-runtime-store.d.ts +0 -39
  495. /package/src/providers/{cloudflare-current-user.d.ts → cloudflare_dns/runtime-user.d.ts} +0 -0
@@ -0,0 +1,121 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ import { HttpRequestError } from "../server/api/http-utils.js";
3
+ import { canonicalJsonBytes, digestBytes } from "./common/encoding.js";
4
+ import { subscriptionId, withSubscription } from "./subscriptions.js";
5
+ async function resourceSubscriptionId(owner, key) {
6
+ return digestBytes(canonicalJsonBytes(["resource-set", owner.service, owner.providerAccountId, key]));
7
+ }
8
+ export async function executeResourceSubscription(store, definition, owner, input, proxy, signal) {
9
+ const member = await subscriptionId(owner, input.requestKey);
10
+ await store.insertFlowTrigger({
11
+ mode: "resource",
12
+ id: member,
13
+ ...owner,
14
+ requestKey: input.requestKey,
15
+ config: input.config,
16
+ endpointUrl: "",
17
+ callbackNonce: "",
18
+ callbackSecret: "",
19
+ checkpoint: null,
20
+ subscription: {},
21
+ reconcileAt: 0,
22
+ status: "active",
23
+ });
24
+ return withSubscription(store, member, signal, async (consumer, saveConsumer) => {
25
+ consumer.connectionRevision = owner.connectionRevision;
26
+ return executeResourceSubscriptionOperation(store, definition, consumer, saveConsumer, input, proxy, signal);
27
+ });
28
+ }
29
+ // The caller must hold the subscription lease until this operation completes.
30
+ export async function executeResourceSubscriptionOperation(store, definition, consumer, saveConsumer, input, proxy, signal) {
31
+ const member = consumer.id;
32
+ const owner = {
33
+ tokenId: consumer.tokenId,
34
+ service: consumer.service,
35
+ connectionId: consumer.connectionId,
36
+ triggerId: consumer.triggerId,
37
+ connectionRevision: consumer.connectionRevision,
38
+ providerAccountId: consumer.providerAccountId,
39
+ };
40
+ if (consumer.status === "deleted") {
41
+ if (!input.active)
42
+ return { outcome: "ready" };
43
+ consumer.status = "active";
44
+ consumer.config = input.config;
45
+ await saveConsumer();
46
+ }
47
+ if (!isDeepStrictEqual(consumer.config, input.config))
48
+ throw new HttpRequestError("invalid_input", "Resource request key is bound to another configuration", 409);
49
+ if (input.active && consumer.status !== "active")
50
+ throw new HttpRequestError("invalid_input", "Resource subscription is being deleted", 409);
51
+ if (!input.active) {
52
+ consumer.status = "deleting";
53
+ await saveConsumer();
54
+ }
55
+ for (const resource of definition.subscriptions(input.config)) {
56
+ const shared = { ...owner, tokenId: "shared-resource" };
57
+ const id = await resourceSubscriptionId(owner, resource.key);
58
+ await store.insertFlowTrigger({
59
+ mode: "resource-set",
60
+ id,
61
+ ...shared,
62
+ requestKey: resource.key,
63
+ config: input.config,
64
+ endpointUrl: "",
65
+ callbackNonce: "",
66
+ callbackSecret: "",
67
+ checkpoint: null,
68
+ subscription: { members: [], ready: false },
69
+ reconcileAt: 0,
70
+ status: "active",
71
+ });
72
+ await withSubscription(store, id, signal, async (record, save) => {
73
+ if (record.status === "abandoned" && input.active) {
74
+ record.status = "active";
75
+ record.subscription = { members: [], ready: false, attempted: true };
76
+ }
77
+ const members = new Set(record.subscription.members);
78
+ if (input.active)
79
+ members.add(member);
80
+ else
81
+ members.delete(member);
82
+ const ready = record.subscription.ready === true;
83
+ let attempted = record.subscription.attempted === true || ready;
84
+ record.subscription = { members: [...members], ready, attempted };
85
+ await save();
86
+ if (members.size > 0 && !ready) {
87
+ attempted = true;
88
+ record.subscription = { members: [...members], ready: false, attempted };
89
+ await save();
90
+ definition.response(await proxy.execute(resource.subscribe, signal));
91
+ record.subscription = { members: [...members], ready: true };
92
+ await save();
93
+ }
94
+ if (members.size === 0 && attempted) {
95
+ record.subscription = { members: [], ready: false, attempted: true };
96
+ await save();
97
+ definition.response(await proxy.execute(resource.unsubscribe, signal));
98
+ record.subscription = { members: [], ready: false };
99
+ await save();
100
+ }
101
+ });
102
+ }
103
+ if (!input.active)
104
+ consumer.status = "deleted";
105
+ await saveConsumer();
106
+ return { outcome: "ready" };
107
+ }
108
+ export async function abandonResourceSubscription(store, definition, consumer, signal) {
109
+ for (const resource of definition.subscriptions(consumer.config)) {
110
+ const id = await resourceSubscriptionId(consumer, resource.key);
111
+ if (!(await store.getFlowTrigger(id)))
112
+ continue;
113
+ await withSubscription(store, id, signal, async (record, save) => {
114
+ const members = record.subscription.members.filter((member) => member !== consumer.id);
115
+ record.subscription = { ...record.subscription, members };
116
+ if (members.length === 0)
117
+ record.status = "abandoned";
118
+ await save();
119
+ });
120
+ }
121
+ }
@@ -0,0 +1,4 @@
1
+ export declare function bytes(value: string): Uint8Array;
2
+ export declare function sameSecret(candidate: string | undefined, expected: string): boolean;
3
+ export declare function verifyBase64Hmac(secret: string, parts: readonly Uint8Array[], signature: string | undefined): Promise<boolean>;
4
+ export declare function verifyHexHmac(secret: string, parts: readonly Uint8Array[], signature: string | undefined): Promise<boolean>;
@@ -0,0 +1,48 @@
1
+ const encoder = new TextEncoder();
2
+ export function bytes(value) {
3
+ return encoder.encode(value);
4
+ }
5
+ export function sameSecret(candidate, expected) {
6
+ return candidate != null && sameBytes(encoder.encode(candidate), encoder.encode(expected));
7
+ }
8
+ export async function verifyBase64Hmac(secret, parts, signature) {
9
+ const candidate = signature == null ? undefined : base64(signature);
10
+ return candidate != null && sameBytes(candidate, await hmac(secret, parts));
11
+ }
12
+ export async function verifyHexHmac(secret, parts, signature) {
13
+ const candidate = signature == null ? undefined : hex(signature);
14
+ return candidate != null && sameBytes(candidate, await hmac(secret, parts));
15
+ }
16
+ async function hmac(secret, parts) {
17
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, [
18
+ "sign",
19
+ ]);
20
+ const size = parts.reduce((total, part) => total + part.byteLength, 0);
21
+ const source = new Uint8Array(size);
22
+ let offset = 0;
23
+ for (const part of parts) {
24
+ source.set(part, offset);
25
+ offset += part.byteLength;
26
+ }
27
+ return new Uint8Array(await crypto.subtle.sign("HMAC", key, source));
28
+ }
29
+ function base64(value) {
30
+ try {
31
+ return Uint8Array.from(atob(value), (character) => character.charCodeAt(0));
32
+ }
33
+ catch {
34
+ return;
35
+ }
36
+ }
37
+ function hex(value) {
38
+ if (value.length == 0 || value.length % 2 != 0 || !/^[0-9a-f]+$/i.test(value))
39
+ return;
40
+ return Uint8Array.from({ length: value.length / 2 }, (_, index) => Number.parseInt(value.slice(index * 2, index * 2 + 2), 16));
41
+ }
42
+ function sameBytes(left, right) {
43
+ let difference = left.byteLength ^ right.byteLength;
44
+ const length = Math.max(left.byteLength, right.byteLength);
45
+ for (let index = 0; index < length; index += 1)
46
+ difference |= (left[index] ?? 0) ^ (right[index] ?? 0);
47
+ return difference == 0;
48
+ }
@@ -0,0 +1,29 @@
1
+ import type { JsonValue } from "./common/types.ts";
2
+ export interface TriggerSubscription {
3
+ mode: "webhook" | "resource" | "resource-set";
4
+ id: string;
5
+ tokenId: string;
6
+ service: string;
7
+ connectionId: string;
8
+ triggerId: string;
9
+ connectionRevision: string;
10
+ providerAccountId: string;
11
+ requestKey: string;
12
+ config: Readonly<Record<string, JsonValue>>;
13
+ endpointUrl: string;
14
+ callbackNonce: string;
15
+ callbackSecret: string;
16
+ checkpoint: JsonValue;
17
+ subscription: Readonly<Record<string, JsonValue>>;
18
+ reconcileAt: number;
19
+ status: "active" | "deleting" | "deleted" | "abandoned";
20
+ }
21
+ export interface TriggerStore {
22
+ list(): Promise<TriggerSubscription[]>;
23
+ listFlowTriggersForMaintenance(now: number, limit: number): Promise<TriggerSubscription[]>;
24
+ insertFlowTrigger(record: TriggerSubscription): Promise<TriggerSubscription>;
25
+ getFlowTrigger(id: string): Promise<TriggerSubscription | null>;
26
+ claimFlowTrigger(id: string, owner: string, now: number, until: number): Promise<boolean>;
27
+ saveFlowTrigger(record: TriggerSubscription, owner: string, now: number): Promise<boolean>;
28
+ releaseFlowTrigger(id: string, owner: string): Promise<void>;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { IntegrationDefinition, IntegrationReceiveResult, IntegrationReconcileResult } from "./common/integration.ts";
2
+ import type { ConnectorProxy } from "./common/proxy.ts";
3
+ import type { TriggerRequest } from "./request.ts";
4
+ import type { TriggerSubscription, TriggerStore } from "./store.ts";
5
+ export type SubscriptionOwner = Pick<TriggerSubscription, "tokenId" | "service" | "connectionId" | "triggerId" | "connectionRevision" | "providerAccountId">;
6
+ export declare function subscriptionId(owner: SubscriptionOwner, requestKey: string): Promise<string>;
7
+ export declare function withSubscription<T>(store: TriggerStore, id: string, signal: AbortSignal, run: (record: TriggerSubscription, save: () => Promise<void>) => Promise<T>): Promise<T>;
8
+ interface SubscriptionState {
9
+ checkpoint: import("./common/types.ts").JsonValue;
10
+ subscription: Readonly<Record<string, import("./common/types.ts").JsonValue>>;
11
+ reconcileAt: number;
12
+ }
13
+ export type SubscriptionResult = SubscriptionState & (IntegrationReconcileResult | {
14
+ result: IntegrationReceiveResult;
15
+ });
16
+ export declare function executeSubscription(store: TriggerStore, definition: IntegrationDefinition, owner: SubscriptionOwner, input: Extract<TriggerRequest, {
17
+ operation: "receive" | "reconcile";
18
+ }>, proxy: ConnectorProxy, signal: AbortSignal): Promise<SubscriptionResult>;
19
+ export declare function executeSubscriptionOperation(record: TriggerSubscription, save: () => Promise<void>, definition: IntegrationDefinition, input: Extract<TriggerRequest, {
20
+ operation: "receive" | "reconcile";
21
+ }>, proxy: ConnectorProxy, signal: AbortSignal): Promise<SubscriptionResult>;
22
+ export {};
@@ -0,0 +1,220 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ import { randomUUIDv7 } from "../core/uuid-v7.js";
4
+ import { HttpRequestError } from "../server/api/http-utils.js";
5
+ import { canonicalJsonBytes, digestBytes } from "./common/encoding.js";
6
+ export async function subscriptionId(owner, requestKey) {
7
+ return digestBytes(canonicalJsonBytes([
8
+ owner.tokenId,
9
+ owner.service,
10
+ owner.connectionId,
11
+ owner.providerAccountId,
12
+ owner.triggerId,
13
+ requestKey,
14
+ ]));
15
+ }
16
+ export async function withSubscription(store, id, signal, run) {
17
+ const lease = randomUUIDv7();
18
+ if (!(await store.claimFlowTrigger(id, lease, Date.now(), Date.now() + 60_000)))
19
+ throw new HttpRequestError("invalid_input", "Trigger subscription is busy", 409);
20
+ try {
21
+ const record = await store.getFlowTrigger(id);
22
+ if (!record)
23
+ throw new HttpRequestError("trigger_not_found", "Subscription not found", 404);
24
+ const save = async () => {
25
+ signal.throwIfAborted();
26
+ if (!(await store.saveFlowTrigger(record, lease, Date.now())))
27
+ throw new HttpRequestError("invalid_input", "Trigger subscription lease expired", 409);
28
+ };
29
+ return await run(record, save);
30
+ }
31
+ finally {
32
+ await store.releaseFlowTrigger(id, lease);
33
+ }
34
+ }
35
+ export async function executeSubscription(store, definition, owner, input, proxy, signal) {
36
+ const id = input.operation === "receive"
37
+ ? input.subscriptionId
38
+ : (input.subscriptionId ?? (await subscriptionId(owner, input.requestKey)));
39
+ if (input.operation === "reconcile" && input.active && !input.subscriptionId) {
40
+ const url = new URL(input.endpointUrl);
41
+ if (url.protocol !== "https:" || url.username || url.password || url.hash)
42
+ throw new HttpRequestError("invalid_input", "A HTTPS callback without credentials or fragment is required", 400);
43
+ await store.insertFlowTrigger({
44
+ mode: "webhook",
45
+ id,
46
+ ...owner,
47
+ requestKey: input.requestKey,
48
+ config: input.config,
49
+ endpointUrl: url.href,
50
+ callbackNonce: randomUUIDv7(),
51
+ callbackSecret: randomBytes(32).toString("base64url"),
52
+ checkpoint: definition.initialState?.checkpoint ?? null,
53
+ subscription: definition.initialState?.subscription ?? {},
54
+ reconcileAt: Date.now(),
55
+ status: "active",
56
+ });
57
+ }
58
+ const existing = await store.getFlowTrigger(id);
59
+ if (!existing) {
60
+ if (input.operation === "reconcile" && !input.active)
61
+ return {
62
+ outcome: "ready",
63
+ checkpoint: null,
64
+ subscription: {},
65
+ reconcileAt: Date.now() + 60_000,
66
+ };
67
+ throw new HttpRequestError("trigger_not_found", "Subscription not found", 404);
68
+ }
69
+ if (existing.tokenId !== owner.tokenId ||
70
+ existing.service !== owner.service ||
71
+ existing.connectionId !== owner.connectionId ||
72
+ existing.triggerId !== owner.triggerId ||
73
+ existing.providerAccountId !== owner.providerAccountId)
74
+ throw new HttpRequestError("trigger_not_found", "Subscription not found", 404);
75
+ return withSubscription(store, id, signal, async (record, save) => {
76
+ return executeSubscriptionOperation(record, save, definition, input, proxy, signal);
77
+ });
78
+ }
79
+ // The caller must hold the subscription lease until this operation completes.
80
+ export async function executeSubscriptionOperation(record, save, definition, input, proxy, signal) {
81
+ const id = record.id;
82
+ const state = {
83
+ get checkpoint() {
84
+ return record.checkpoint;
85
+ },
86
+ get subscription() {
87
+ return record.subscription;
88
+ },
89
+ saveCheckpoint: async (checkpoint) => {
90
+ record.checkpoint = checkpoint;
91
+ await save();
92
+ },
93
+ saveSubscription: async (subscription, reconcileAt) => {
94
+ record.subscription = subscription;
95
+ record.reconcileAt = reconcileAt.getTime();
96
+ await save();
97
+ },
98
+ };
99
+ if (input.operation === "reconcile") {
100
+ if (record.status === "deleted" && !input.active)
101
+ return {
102
+ outcome: "ready",
103
+ checkpoint: record.checkpoint,
104
+ subscription: { id },
105
+ reconcileAt: record.reconcileAt,
106
+ };
107
+ const url = new URL(input.endpointUrl);
108
+ if (url.protocol !== "https:" || url.username || url.password || url.hash)
109
+ throw new HttpRequestError("invalid_input", "A HTTPS callback without credentials or fragment is required", 400);
110
+ if (record.status === "abandoned")
111
+ throw new HttpRequestError("trigger_abandoned", "Create a new request key after abandoning cleanup.", 409);
112
+ if (record.status === "deleted") {
113
+ record.config = input.config;
114
+ record.endpointUrl = url.href;
115
+ record.callbackNonce = randomUUIDv7();
116
+ record.callbackSecret = randomBytes(32).toString("base64url");
117
+ record.checkpoint = definition.initialState?.checkpoint ?? null;
118
+ record.subscription = definition.initialState?.subscription ?? {};
119
+ record.reconcileAt = Date.now();
120
+ record.status = "active";
121
+ await save();
122
+ }
123
+ if (!isDeepStrictEqual(record.config, input.config) || record.endpointUrl !== url.href)
124
+ throw new HttpRequestError("invalid_input", "Subscription request key is already bound to another configuration", 409);
125
+ if (!input.active) {
126
+ record.status = "deleting";
127
+ await save();
128
+ }
129
+ if (input.active && record.status !== "active")
130
+ throw new HttpRequestError("invalid_input", "Subscription is being deleted", 409);
131
+ const callback = new URL(record.endpointUrl);
132
+ callback.searchParams.set("connector_subscription", record.callbackNonce);
133
+ const result = await definition.reconcile({
134
+ active: input.active,
135
+ config: record.config,
136
+ endpointUrl: callback.href,
137
+ callbackSecret: record.callbackSecret,
138
+ idempotencyKey: record.callbackNonce,
139
+ connector: proxy,
140
+ now: new Date(),
141
+ state,
142
+ signal,
143
+ });
144
+ if (!input.active && result.outcome === "ready") {
145
+ record.status = "deleted";
146
+ await save();
147
+ }
148
+ return {
149
+ ...result,
150
+ checkpoint: record.checkpoint,
151
+ subscription: { id },
152
+ reconcileAt: record.reconcileAt,
153
+ };
154
+ }
155
+ if (record.status !== "active")
156
+ return {
157
+ result: { outcome: "ignored", reason: "Subscription is not active" },
158
+ checkpoint: record.checkpoint,
159
+ subscription: { id },
160
+ reconcileAt: record.reconcileAt,
161
+ };
162
+ if (input.query.connector_subscription !== record.callbackNonce)
163
+ return {
164
+ result: { outcome: "respond", status: 404, body: "", contentType: "text/plain" },
165
+ checkpoint: record.checkpoint,
166
+ subscription: { id },
167
+ reconcileAt: record.reconcileAt,
168
+ };
169
+ if (!definition.snapshot.endpoint.methods.includes(input.method))
170
+ throw new HttpRequestError("invalid_input", "Unsupported webhook method.");
171
+ const rawBody = Uint8Array.from(Buffer.from(input.rawBody, "base64"));
172
+ if (rawBody.byteLength > 64 * 1024)
173
+ throw new HttpRequestError("invalid_input", "Webhook body is too large", 400);
174
+ if (!rawBody.byteLength && !definition.snapshot.endpoint.body.allowEmpty)
175
+ throw new HttpRequestError("invalid_input", "Webhook body is required.");
176
+ const type = input.headers["content-type"]?.split(";")[0]?.trim().toLowerCase();
177
+ if (rawBody.byteLength && type !== "application/json")
178
+ throw new HttpRequestError("invalid_input", "Webhook content type must be application/json.");
179
+ let payload = null;
180
+ if (rawBody.byteLength > 0) {
181
+ const text = new TextDecoder().decode(rawBody);
182
+ try {
183
+ payload =
184
+ type === "application/x-www-form-urlencoded" ? Object.fromEntries(new URLSearchParams(text)) : JSON.parse(text);
185
+ }
186
+ catch (error) {
187
+ if (error instanceof SyntaxError)
188
+ throw new HttpRequestError("invalid_input", "Invalid webhook JSON payload", 400);
189
+ throw error;
190
+ }
191
+ }
192
+ if (Array.isArray(payload) && !definition.snapshot.endpoint.body.allowArray)
193
+ throw new HttpRequestError("invalid_input", "Webhook body must not be an array.");
194
+ const result = await definition.receive({
195
+ bindingId: id,
196
+ callbackSecret: record.callbackSecret,
197
+ config: record.config,
198
+ connector: proxy,
199
+ current: input.current,
200
+ admit: input.admit,
201
+ method: input.method,
202
+ now: new Date(),
203
+ payload: payload,
204
+ rawBody,
205
+ header: (name) => input.headers[name.toLowerCase()],
206
+ query: (name) => input.query[name],
207
+ state,
208
+ signal,
209
+ });
210
+ if ("checkpoint" in result && result.checkpoint !== undefined) {
211
+ record.checkpoint = result.checkpoint;
212
+ await save();
213
+ }
214
+ return {
215
+ result,
216
+ checkpoint: record.checkpoint,
217
+ subscription: { id },
218
+ reconcileAt: record.reconcileAt,
219
+ };
220
+ }
@@ -0,0 +1,34 @@
1
+ import type { CatalogStore } from "../catalog-store.ts";
2
+ import type { ConnectionService } from "../connection-service.ts";
3
+ import type { ActionPolicySnapshot } from "../core/action-policy.ts";
4
+ import type { IProviderLoader } from "../providers/provider-loader.ts";
5
+ import type { RuntimeGrant } from "../server/storage/runtime-token-service.ts";
6
+ import type { TriggerRequest } from "./request.ts";
7
+ import type { TriggerSubscription, TriggerStore } from "./store.ts";
8
+ interface TriggerRunnerOptions {
9
+ catalog: CatalogStore;
10
+ providerLoader: IProviderLoader;
11
+ connections: ConnectionService;
12
+ store: TriggerStore;
13
+ }
14
+ export interface RunTriggerInput {
15
+ service: string;
16
+ triggerId: string;
17
+ connectionName?: string;
18
+ connectionId?: string;
19
+ policy: ActionPolicySnapshot;
20
+ grant?: RuntimeGrant;
21
+ request: TriggerRequest;
22
+ signal: AbortSignal;
23
+ }
24
+ export declare class TriggerRunner {
25
+ private readonly options;
26
+ constructor(options: TriggerRunnerOptions);
27
+ run(input: RunTriggerInput): Promise<unknown>;
28
+ cleanup(record: TriggerSubscription, save: () => Promise<void>, signal: AbortSignal): Promise<void>;
29
+ abandonResource(record: TriggerSubscription, signal: AbortSignal): Promise<void>;
30
+ private definition;
31
+ private target;
32
+ private providerOperation;
33
+ }
34
+ export {};
@@ -0,0 +1,169 @@
1
+ import { ConnectionError } from "../connection-service.js";
2
+ import { optionalInteger, optionalRecord } from "../core/cast.js";
3
+ import { HttpRequestError } from "../server/api/http-utils.js";
4
+ import { mapConnectionErrorStatus } from "../server/api/runtime-api.js";
5
+ import { resolveTriggerConfig } from "./common/config.js";
6
+ import { validateListenerPage } from "./common/integration.js";
7
+ import { executeResourceSubscription, executeResourceSubscriptionOperation, abandonResourceSubscription, } from "./resources.js";
8
+ import { executeSubscription, executeSubscriptionOperation } from "./subscriptions.js";
9
+ export class TriggerRunner {
10
+ options;
11
+ constructor(options) {
12
+ this.options = options;
13
+ }
14
+ async run(input) {
15
+ const decision = input.policy.evaluateTrigger(input.triggerId);
16
+ if (!decision.allowed)
17
+ throw new HttpRequestError(decision.code, decision.message, 403);
18
+ const stateful = input.request.operation !== "read" && input.request.operation !== "options";
19
+ if (stateful && !input.grant)
20
+ throw new HttpRequestError("trigger_owner_required", "Stateful Trigger operations require a persistent runtime token.", 403);
21
+ const definition = await this.definition(input.service, input.triggerId);
22
+ const target = await this.target(input.service, input.connectionName, input.connectionId, input.signal, input.policy);
23
+ const request = input.request;
24
+ if (request.operation === "receive") {
25
+ if (definition.snapshot.type !== "integration" || ("eventSource" in definition && definition.eventSource))
26
+ throw new HttpRequestError("invalid_input", "This Trigger has no remote webhook.");
27
+ return this.providerOperation(() => executeSubscription(this.options.store, definition, { ...target.owner, tokenId: input.grant.tokenId, triggerId: input.triggerId }, request, target.proxy, input.signal));
28
+ }
29
+ const config = resolveTriggerConfig(definition.snapshot.configInputs, request.config, request.operation === "options");
30
+ const context = { config, connector: target.proxy, now: new Date(), signal: input.signal };
31
+ return this.providerOperation(async () => {
32
+ switch (request.operation) {
33
+ case "options": {
34
+ if (!definition.configOptions ||
35
+ !definition.snapshot.configInputs.some((field) => "handle" in field && field.handle === request.field))
36
+ throw new HttpRequestError("invalid_input", "This Trigger has no options for the selected field.");
37
+ return definition.configOptions({ ...context, field: request.field });
38
+ }
39
+ case "read": {
40
+ if (definition.snapshot.type === "poll")
41
+ return definition.poll({ ...context, checkpoint: request.checkpoint });
42
+ const listener = definition.listener;
43
+ if (!listener)
44
+ throw new HttpRequestError("invalid_input", "This Trigger cannot be read.");
45
+ const page = await listener.read({ ...context, checkpoint: request.checkpoint });
46
+ validateListenerPage(page);
47
+ return page;
48
+ }
49
+ case "reconcile":
50
+ if (definition.snapshot.type !== "integration" || definition.eventSource)
51
+ throw new HttpRequestError("invalid_input", "This Trigger has no remote webhook.");
52
+ return executeSubscription(this.options.store, definition, { ...target.owner, tokenId: input.grant.tokenId, triggerId: input.triggerId }, { ...request, config }, target.proxy, input.signal);
53
+ case "resource":
54
+ if (!definition.resources)
55
+ throw new HttpRequestError("invalid_input", "This Trigger has no shared resource.");
56
+ return executeResourceSubscription(this.options.store, definition.resources, { ...target.owner, tokenId: input.grant.tokenId, triggerId: input.triggerId }, { ...request, config }, target.proxy, input.signal);
57
+ }
58
+ });
59
+ }
60
+ async cleanup(record, save, signal) {
61
+ const target = await this.target(record.service, undefined, record.connectionId, signal);
62
+ if (target.owner.providerAccountId !== record.providerAccountId)
63
+ throw new HttpRequestError("trigger_connection_error", "The subscription's original provider account is unavailable.", 409);
64
+ record.connectionRevision = target.owner.connectionRevision;
65
+ const definition = await this.definition(record.service, record.triggerId);
66
+ if (record.mode === "resource") {
67
+ if (!definition.resources)
68
+ throw new HttpRequestError("trigger_not_supported", "Resource subscriptions are unavailable.", 501);
69
+ await this.providerOperation(() => executeResourceSubscriptionOperation(this.options.store, definition.resources, record, save, { operation: "resource", config: record.config, active: false, requestKey: record.requestKey }, target.proxy, signal));
70
+ }
71
+ else {
72
+ if (definition.snapshot.type !== "integration")
73
+ throw new HttpRequestError("trigger_not_found", "The remote Trigger definition is unavailable.", 404);
74
+ await this.providerOperation(() => executeSubscriptionOperation(record, save, definition, {
75
+ operation: "reconcile",
76
+ config: record.config,
77
+ endpointUrl: record.endpointUrl,
78
+ requestKey: record.requestKey,
79
+ subscriptionId: record.id,
80
+ active: false,
81
+ }, target.proxy, signal));
82
+ }
83
+ }
84
+ async abandonResource(record, signal) {
85
+ const definition = await this.definition(record.service, record.triggerId);
86
+ const resources = definition.resources;
87
+ if (!resources)
88
+ throw new HttpRequestError("trigger_not_supported", "Resource subscriptions are unavailable.", 501);
89
+ await abandonResourceSubscription(this.options.store, resources, record, signal);
90
+ }
91
+ async definition(service, triggerId) {
92
+ if (!this.options.catalog.providers.some((provider) => provider.service === service))
93
+ throw new HttpRequestError("provider_not_found", "Provider not found.", 404);
94
+ const definitions = await this.options.providerLoader.loadTriggerDefinitions?.(service);
95
+ const definition = definitions?.find((candidate) => candidate.snapshot.key === triggerId && candidate.snapshot.provider === service);
96
+ if (!definition)
97
+ throw new HttpRequestError("trigger_not_found", "Trigger not found.", 404);
98
+ return definition;
99
+ }
100
+ async target(service, connectionName, connectionId, signal, policy) {
101
+ try {
102
+ const summary = await this.options.connections.getConnectionSummary(service, connectionName, connectionId);
103
+ const permission = policy?.evaluateConnection(summary?.id);
104
+ if (permission && !permission.allowed)
105
+ throw new HttpRequestError(permission.code, permission.message, 403);
106
+ const target = await this.options.connections.resolveForExecution(service, connectionName, connectionId);
107
+ if (target.kind !== "local")
108
+ throw new HttpRequestError("trigger_source_not_supported", "Triggers require a local connection; this connection source is not supported.", 501);
109
+ const selected = policy?.evaluateConnection(target.summary?.id);
110
+ if (selected && !selected.allowed)
111
+ throw new HttpRequestError(selected.code, selected.message, 403);
112
+ const credential = await target.getCredential(service);
113
+ if (!credential || credential.authType === "no_auth" || !target.summary)
114
+ throw new HttpRequestError("connection_not_found", "Trigger connection not found.", 404);
115
+ const stored = await this.options.connections.getStoredConnection(target.summary.id);
116
+ if (!stored ||
117
+ stored.source === "saas" ||
118
+ stored.credential.authType === "no_auth" ||
119
+ stored.credential.profile.accountId !== credential.profile.accountId)
120
+ throw new HttpRequestError("trigger_connection_error", "The selected connection changed during Trigger execution.", 409);
121
+ const executor = await this.options.providerLoader.loadProxyExecutor(service);
122
+ if (!executor)
123
+ throw new HttpRequestError("trigger_not_supported", "The provider has no Trigger transport.", 501);
124
+ const proxy = {
125
+ execute: async (request, requestSignal) => {
126
+ signal.throwIfAborted();
127
+ const result = await executor(request, {
128
+ getCredential: target.getCredential,
129
+ signal: requestSignal ?? signal,
130
+ });
131
+ if (result.ok)
132
+ return result.response;
133
+ const status = optionalInteger(optionalRecord(result.error.details)?.status) ?? 502;
134
+ return { status, data: { error: result.error.message } };
135
+ },
136
+ };
137
+ return {
138
+ proxy,
139
+ owner: {
140
+ service,
141
+ connectionId: stored.id,
142
+ connectionRevision: stored.revision,
143
+ providerAccountId: credential.profile.accountId,
144
+ },
145
+ };
146
+ }
147
+ catch (error) {
148
+ if (error instanceof ConnectionError)
149
+ throw new HttpRequestError(error.code, error.message, mapConnectionErrorStatus(error));
150
+ throw error;
151
+ }
152
+ }
153
+ async providerOperation(run) {
154
+ try {
155
+ return await run();
156
+ }
157
+ catch (error) {
158
+ if (error instanceof Error) {
159
+ if (error.name === "IntegrationConnectionError" || error.name === "PollConnectionError")
160
+ throw new HttpRequestError("trigger_connection_error", "The Trigger connection could not be used.", 409);
161
+ if (error.name === "TransientIntegrationError" || error.name === "TransientPollError")
162
+ throw new HttpRequestError("proxy_upstream_error", "The Trigger provider is temporarily unavailable.", 503);
163
+ if (error.name === "PermanentIntegrationError" || error.name === "PermanentPollError")
164
+ throw new HttpRequestError("invalid_input", error.message);
165
+ }
166
+ throw error;
167
+ }
168
+ }
169
+ }
@@ -1 +0,0 @@
1
- export declare const sentryProviderScopes: string[];
@@ -1,7 +0,0 @@
1
- export const sentryProviderScopes = [
2
- "org:read",
3
- "project:read",
4
- "project:releases",
5
- "event:read",
6
- "event:write",
7
- ];