@oomol-lab/open-connector 1.7.0 → 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 (288) 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 +916 -76
  4. package/assets/open-connector/catalog/apps/cal.json +24 -6
  5. package/assets/open-connector/catalog/apps/discordbot.json +2 -2
  6. package/assets/open-connector/catalog/apps/enormail.json +411 -0
  7. package/assets/open-connector/catalog/apps/feishu_app_bot.json +158 -0
  8. package/assets/open-connector/catalog/apps/github.json +275 -0
  9. package/assets/open-connector/catalog/apps/gitlab.json +125 -0
  10. package/assets/open-connector/catalog/apps/gmail.json +151 -0
  11. package/assets/open-connector/catalog/apps/googlecalendar.json +206 -0
  12. package/assets/open-connector/catalog/apps/googledrive.json +479 -0
  13. package/assets/open-connector/catalog/apps/googlesheets.json +144 -0
  14. package/assets/open-connector/catalog/apps/hithink_finance.json +6 -3
  15. package/assets/open-connector/catalog/apps/indexed.json +1115 -0
  16. package/assets/open-connector/catalog/apps/linear.json +116 -0
  17. package/assets/open-connector/catalog/apps/notion.json +142 -0
  18. package/assets/open-connector/catalog/apps/one_drive.json +185 -0
  19. package/assets/open-connector/catalog/apps/outlook.json +182 -0
  20. package/assets/open-connector/catalog/apps/shopify.json +282 -0
  21. package/assets/open-connector/catalog/apps/slack.json +182 -0
  22. package/assets/open-connector/catalog/apps/spotify.json +46 -43
  23. package/assets/open-connector/catalog/apps/stripe.json +96 -0
  24. package/assets/open-connector/catalog/apps/telegram.json +138 -0
  25. package/assets/open-connector/catalog/apps/weixin_store.json +543 -2
  26. package/assets/open-connector/catalog/apps/woocommerce.json +127 -0
  27. package/assets/open-connector/catalog/apps/zendesk.json +152 -0
  28. package/assets/open-connector/catalog/apps/zerotier.json +9 -9
  29. package/assets/open-connector/catalog/apps-index.json +1 -1
  30. package/assets/open-connector/migrations/0014_saas_project.sql +55 -0
  31. package/assets/open-connector/migrations/0015_saas_cleanup_runtime.sql +8 -0
  32. package/assets/open-connector/migrations/0016_trigger_policy.sql +1 -0
  33. package/assets/open-connector/migrations/0017_trigger_subscriptions.sql +17 -0
  34. package/assets/open-connector/migrations/postgresql/0014_saas_project.sql +55 -0
  35. package/assets/open-connector/migrations/postgresql/0015_saas_cleanup_runtime.sql +8 -0
  36. package/assets/open-connector/migrations/postgresql/0016_trigger_policy.sql +1 -0
  37. package/assets/open-connector/migrations/postgresql/0017_trigger_subscriptions.sql +17 -0
  38. package/package.json +2 -2
  39. package/src/connection-service.d.ts +40 -7
  40. package/src/connection-service.js +60 -18
  41. package/src/core/action-policy.d.ts +8 -1
  42. package/src/core/action-policy.js +51 -0
  43. package/src/core/cast.d.ts +3 -0
  44. package/src/core/cast.js +4 -1
  45. package/src/core/guarded-fetch.d.ts +5 -0
  46. package/src/core/guarded-fetch.js +13 -4
  47. package/src/core/remote-http.d.ts +33 -0
  48. package/src/core/remote-http.js +104 -0
  49. package/src/core/request.d.ts +1 -0
  50. package/src/core/request.js +7 -0
  51. package/src/core/types.d.ts +4 -0
  52. package/src/marketplace/marketplace-service.d.ts +0 -1
  53. package/src/marketplace/marketplace-service.js +80 -92
  54. package/src/mcp.js +19 -5
  55. package/src/oauth/oauth-flow-service.d.ts +8 -1
  56. package/src/oauth/oauth-flow-service.js +10 -4
  57. package/src/providers/action-contracts.generated.d.ts +4 -2
  58. package/src/providers/airtable/executors.d.ts +3 -0
  59. package/src/providers/airtable/executors.js +2 -0
  60. package/src/providers/airtable/trigger-on-record-changed.d.ts +2 -0
  61. package/src/providers/airtable/trigger-on-record-changed.definition.d.ts +4 -0
  62. package/src/providers/airtable/trigger-on-record-changed.definition.js +54 -0
  63. package/src/providers/airtable/trigger-on-record-changed.js +235 -0
  64. package/src/providers/aisa/executors.js +196 -22
  65. package/src/providers/cal/actions.js +5 -1
  66. package/src/providers/enormail/executors.d.ts +4 -0
  67. package/src/providers/enormail/executors.js +97 -0
  68. package/src/providers/feishu_app_bot/executors.d.ts +3 -0
  69. package/src/providers/feishu_app_bot/executors.js +2 -0
  70. package/src/providers/feishu_app_bot/trigger-config.d.ts +1 -0
  71. package/src/providers/feishu_app_bot/trigger-config.js +10 -0
  72. package/src/providers/feishu_app_bot/trigger-on-event.d.ts +2 -0
  73. package/src/providers/feishu_app_bot/trigger-on-event.definition.d.ts +4 -0
  74. package/src/providers/feishu_app_bot/trigger-on-event.definition.js +63 -0
  75. package/src/providers/feishu_app_bot/trigger-on-event.js +29 -0
  76. package/src/providers/feishu_app_bot/trigger-subscriptions.d.ts +5 -0
  77. package/src/providers/feishu_app_bot/trigger-subscriptions.js +70 -0
  78. package/src/providers/github/executors.d.ts +3 -0
  79. package/src/providers/github/executors.js +6 -0
  80. package/src/providers/github/trigger-on-repo-event.d.ts +2 -0
  81. package/src/providers/github/trigger-on-repo-event.definition.d.ts +4 -0
  82. package/src/providers/github/trigger-on-repo-event.definition.js +94 -0
  83. package/src/providers/github/trigger-on-repo-event.js +168 -0
  84. package/src/providers/github/trigger-watch-pull-request.d.ts +2 -0
  85. package/src/providers/github/trigger-watch-pull-request.definition.d.ts +4 -0
  86. package/src/providers/github/trigger-watch-pull-request.definition.js +49 -0
  87. package/src/providers/github/trigger-watch-pull-request.js +106 -0
  88. package/src/providers/gitlab/executors.d.ts +3 -0
  89. package/src/providers/gitlab/executors.js +2 -0
  90. package/src/providers/gitlab/trigger-on-project-event.d.ts +2 -0
  91. package/src/providers/gitlab/trigger-on-project-event.definition.d.ts +5 -0
  92. package/src/providers/gitlab/trigger-on-project-event.definition.js +63 -0
  93. package/src/providers/gitlab/trigger-on-project-event.js +186 -0
  94. package/src/providers/gmail/executors.d.ts +3 -0
  95. package/src/providers/gmail/executors.js +2 -0
  96. package/src/providers/gmail/trigger-on-message-received.d.ts +2 -0
  97. package/src/providers/gmail/trigger-on-message-received.definition.d.ts +4 -0
  98. package/src/providers/gmail/trigger-on-message-received.definition.js +74 -0
  99. package/src/providers/gmail/trigger-on-message-received.js +232 -0
  100. package/src/providers/googlecalendar/executors.d.ts +3 -0
  101. package/src/providers/googlecalendar/executors.js +2 -0
  102. package/src/providers/googlecalendar/trigger-on-event-changed.d.ts +2 -0
  103. package/src/providers/googlecalendar/trigger-on-event-changed.definition.d.ts +4 -0
  104. package/src/providers/googlecalendar/trigger-on-event-changed.definition.js +74 -0
  105. package/src/providers/googlecalendar/trigger-on-event-changed.js +233 -0
  106. package/src/providers/googledrive/executors.d.ts +3 -0
  107. package/src/providers/googledrive/executors.js +7 -0
  108. package/src/providers/googledrive/trigger-changes.d.ts +12 -0
  109. package/src/providers/googledrive/trigger-changes.definition.d.ts +7 -0
  110. package/src/providers/googledrive/trigger-changes.definition.js +101 -0
  111. package/src/providers/googledrive/trigger-changes.js +452 -0
  112. package/src/providers/googledrive/trigger-on-file-change.d.ts +2 -0
  113. package/src/providers/googledrive/trigger-on-file-change.definition.d.ts +4 -0
  114. package/src/providers/googledrive/trigger-on-file-change.definition.js +77 -0
  115. package/src/providers/googledrive/trigger-on-file-change.js +258 -0
  116. package/src/providers/googlesheets/executors.d.ts +3 -0
  117. package/src/providers/googlesheets/executors.js +2 -0
  118. package/src/providers/googlesheets/trigger-on-row-added.d.ts +2 -0
  119. package/src/providers/googlesheets/trigger-on-row-added.definition.d.ts +4 -0
  120. package/src/providers/googlesheets/trigger-on-row-added.definition.js +54 -0
  121. package/src/providers/googlesheets/trigger-on-row-added.js +234 -0
  122. package/src/providers/hithink_finance/runtime.js +1 -1
  123. package/src/providers/indexed/executors.d.ts +4 -0
  124. package/src/providers/indexed/executors.js +16 -0
  125. package/src/providers/indexed/runtime.d.ts +26 -0
  126. package/src/providers/indexed/runtime.js +129 -0
  127. package/src/providers/linear/executors.d.ts +3 -0
  128. package/src/providers/linear/executors.js +2 -0
  129. package/src/providers/linear/trigger-on-issue-changed.d.ts +2 -0
  130. package/src/providers/linear/trigger-on-issue-changed.definition.d.ts +5 -0
  131. package/src/providers/linear/trigger-on-issue-changed.definition.js +43 -0
  132. package/src/providers/linear/trigger-on-issue-changed.js +215 -0
  133. package/src/providers/notion/executors.d.ts +3 -0
  134. package/src/providers/notion/executors.js +2 -0
  135. package/src/providers/notion/trigger-on-database-page-event.d.ts +2 -0
  136. package/src/providers/notion/trigger-on-database-page-event.definition.d.ts +4 -0
  137. package/src/providers/notion/trigger-on-database-page-event.definition.js +63 -0
  138. package/src/providers/notion/trigger-on-database-page-event.js +293 -0
  139. package/src/providers/one_drive/executors.d.ts +3 -0
  140. package/src/providers/one_drive/executors.js +2 -0
  141. package/src/providers/one_drive/trigger-on-item-changed.d.ts +2 -0
  142. package/src/providers/one_drive/trigger-on-item-changed.definition.d.ts +4 -0
  143. package/src/providers/one_drive/trigger-on-item-changed.definition.js +63 -0
  144. package/src/providers/one_drive/trigger-on-item-changed.js +214 -0
  145. package/src/providers/outlook/executors.d.ts +3 -0
  146. package/src/providers/outlook/executors.js +2 -0
  147. package/src/providers/outlook/trigger-on-message-received.d.ts +2 -0
  148. package/src/providers/outlook/trigger-on-message-received.definition.d.ts +4 -0
  149. package/src/providers/outlook/trigger-on-message-received.definition.js +93 -0
  150. package/src/providers/outlook/trigger-on-message-received.js +226 -0
  151. package/src/providers/outlook_calendar/executors.js +6 -0
  152. package/src/providers/provider-loader.d.ts +5 -0
  153. package/src/providers/provider-loader.js +4 -0
  154. package/src/providers/registry.generated.js +2 -0
  155. package/src/providers/shopify/executors.d.ts +3 -0
  156. package/src/providers/shopify/executors.js +2 -0
  157. package/src/providers/shopify/trigger-on-shop-event.d.ts +2 -0
  158. package/src/providers/shopify/trigger-on-shop-event.definition.d.ts +4 -0
  159. package/src/providers/shopify/trigger-on-shop-event.definition.js +214 -0
  160. package/src/providers/shopify/trigger-on-shop-event.js +165 -0
  161. package/src/providers/slack/executors.d.ts +3 -0
  162. package/src/providers/slack/executors.js +2 -0
  163. package/src/providers/slack/trigger-on-message-posted.d.ts +2 -0
  164. package/src/providers/slack/trigger-on-message-posted.definition.d.ts +4 -0
  165. package/src/providers/slack/trigger-on-message-posted.definition.js +80 -0
  166. package/src/providers/slack/trigger-on-message-posted.js +176 -0
  167. package/src/providers/spotify/runtime.js +15 -4
  168. package/src/providers/stripe/executors.d.ts +3 -0
  169. package/src/providers/stripe/executors.js +2 -0
  170. package/src/providers/stripe/trigger-on-event.d.ts +2 -0
  171. package/src/providers/stripe/trigger-on-event.definition.d.ts +4 -0
  172. package/src/providers/stripe/trigger-on-event.definition.js +43 -0
  173. package/src/providers/stripe/trigger-on-event.js +212 -0
  174. package/src/providers/telegram/executors.d.ts +3 -0
  175. package/src/providers/telegram/executors.js +2 -0
  176. package/src/providers/telegram/trigger-on-update.d.ts +2 -0
  177. package/src/providers/telegram/trigger-on-update.definition.d.ts +5 -0
  178. package/src/providers/telegram/trigger-on-update.definition.js +78 -0
  179. package/src/providers/telegram/trigger-on-update.js +141 -0
  180. package/src/providers/weixin_store/access-token.d.ts +2 -1
  181. package/src/providers/weixin_store/access-token.js +15 -4
  182. package/src/providers/weixin_store/executors.js +97 -12
  183. package/src/providers/woocommerce/executors.d.ts +3 -0
  184. package/src/providers/woocommerce/executors.js +2 -0
  185. package/src/providers/woocommerce/trigger-on-store-event.d.ts +2 -0
  186. package/src/providers/woocommerce/trigger-on-store-event.definition.d.ts +4 -0
  187. package/src/providers/woocommerce/trigger-on-store-event.definition.js +55 -0
  188. package/src/providers/woocommerce/trigger-on-store-event.js +179 -0
  189. package/src/providers/zendesk/executors.d.ts +3 -0
  190. package/src/providers/zendesk/executors.js +2 -0
  191. package/src/providers/zendesk/trigger-on-event.d.ts +2 -0
  192. package/src/providers/zendesk/trigger-on-event.definition.d.ts +5 -0
  193. package/src/providers/zendesk/trigger-on-event.definition.js +101 -0
  194. package/src/providers/zendesk/trigger-on-event.js +188 -0
  195. package/src/saas/saas-cleanup-service.d.ts +26 -0
  196. package/src/saas/saas-cleanup-service.js +124 -0
  197. package/src/saas/saas-client.d.ts +86 -0
  198. package/src/saas/saas-client.js +369 -0
  199. package/src/saas/saas-execution-service.d.ts +15 -0
  200. package/src/saas/saas-execution-service.js +21 -0
  201. package/src/saas/saas-oauth-service.d.ts +25 -0
  202. package/src/saas/saas-oauth-service.js +197 -0
  203. package/src/saas/saas-project-service.d.ts +61 -0
  204. package/src/saas/saas-project-service.js +211 -0
  205. package/src/server/actions/action-idempotency.d.ts +1 -0
  206. package/src/server/actions/action-idempotency.js +1 -0
  207. package/src/server/actions/action-runner.d.ts +7 -0
  208. package/src/server/actions/action-runner.js +43 -7
  209. package/src/server/actions/run-log-summary.js +9 -0
  210. package/src/server/api/auth.d.ts +1 -0
  211. package/src/server/api/auth.js +13 -2
  212. package/src/server/api/cache-policy.js +4 -1
  213. package/src/server/api/connection-input.d.ts +7 -1
  214. package/src/server/api/connection-input.js +7 -1
  215. package/src/server/api/connection-routes.d.ts +3 -1
  216. package/src/server/api/connection-routes.js +21 -3
  217. package/src/server/api/http-utils.d.ts +4 -3
  218. package/src/server/api/oauth-completion-page.d.ts +124 -0
  219. package/src/server/api/oauth-completion-page.js +113 -18
  220. package/src/server/api/openapi.js +112 -14
  221. package/src/server/api/policy-input.js +6 -0
  222. package/src/server/api/runtime-api.d.ts +10 -2
  223. package/src/server/api/runtime-api.js +17 -4
  224. package/src/server/api/saas-completion-page.d.ts +2 -0
  225. package/src/server/api/saas-completion-page.js +103 -0
  226. package/src/server/connect-app.d.ts +5 -0
  227. package/src/server/connect-app.js +50 -0
  228. package/src/server/connect-server.d.ts +12 -0
  229. package/src/server/connect-server.js +147 -13
  230. package/src/server/connector-runtime.d.ts +3 -1
  231. package/src/server/connector-runtime.js +5 -2
  232. package/src/server/files/transit-files.js +16 -7
  233. package/src/server/proxy/proxy-runner.d.ts +5 -1
  234. package/src/server/proxy/proxy-runner.js +72 -26
  235. package/src/server/storage/connection-request-store.d.ts +41 -1
  236. package/src/server/storage/connection-request-store.js +245 -20
  237. package/src/server/storage/connection-store.d.ts +16 -0
  238. package/src/server/storage/connection-store.js +119 -0
  239. package/src/server/storage/node-runtime-database.js +3 -3
  240. package/src/server/storage/{postgres-migrations.d.ts → postgres/migrations.d.ts} +2 -2
  241. package/src/server/storage/{postgres-migrations.js → postgres/migrations.js} +1 -1
  242. package/src/server/storage/postgres/runtime-store.d.ts +43 -0
  243. package/src/server/storage/{postgres-runtime-store.js → postgres/runtime-store.js} +59 -94
  244. package/src/server/storage/runtime-database.d.ts +4 -0
  245. package/src/server/storage/runtime-sql.d.ts +1 -1
  246. package/src/server/storage/runtime-sql.js +2 -1
  247. package/src/server/storage/runtime-store.d.ts +1 -0
  248. package/src/server/storage/runtime-token-service.d.ts +2 -0
  249. package/src/server/storage/runtime-token-service.js +3 -0
  250. package/src/server/storage/saas-project-store.d.ts +77 -0
  251. package/src/server/storage/saas-project-store.js +273 -0
  252. package/src/server/storage/{sqlite-runtime-store.d.ts → sqlite/runtime-store.d.ts} +21 -25
  253. package/src/server/storage/{sqlite-runtime-store.js → sqlite/runtime-store.js} +100 -115
  254. package/src/server/storage/trigger-store.d.ts +16 -0
  255. package/src/server/storage/trigger-store.js +96 -0
  256. package/src/triggers/common/config.d.ts +2 -0
  257. package/src/triggers/common/config.js +17 -0
  258. package/src/triggers/common/configOptions.d.ts +13 -0
  259. package/src/triggers/common/configOptions.js +1 -0
  260. package/src/triggers/common/encoding.d.ts +3 -0
  261. package/src/triggers/common/encoding.js +19 -0
  262. package/src/triggers/common/integration.d.ts +115 -0
  263. package/src/triggers/common/integration.js +31 -0
  264. package/src/triggers/common/json.d.ts +6 -0
  265. package/src/triggers/common/json.js +91 -0
  266. package/src/triggers/common/poll.d.ts +41 -0
  267. package/src/triggers/common/poll.js +15 -0
  268. package/src/triggers/common/proxy.d.ts +14 -0
  269. package/src/triggers/common/proxy.js +1 -0
  270. package/src/triggers/common/types.d.ts +42 -0
  271. package/src/triggers/common/types.js +1 -0
  272. package/src/triggers/maintenance.d.ts +40 -0
  273. package/src/triggers/maintenance.js +120 -0
  274. package/src/triggers/metadata.d.ts +8 -0
  275. package/src/triggers/metadata.js +1 -0
  276. package/src/triggers/request.d.ts +33 -0
  277. package/src/triggers/request.js +52 -0
  278. package/src/triggers/resources.d.ts +12 -0
  279. package/src/triggers/resources.js +121 -0
  280. package/src/triggers/signature.d.ts +4 -0
  281. package/src/triggers/signature.js +48 -0
  282. package/src/triggers/store.d.ts +29 -0
  283. package/src/triggers/store.js +1 -0
  284. package/src/triggers/subscriptions.d.ts +22 -0
  285. package/src/triggers/subscriptions.js +220 -0
  286. package/src/triggers/trigger-runner.d.ts +34 -0
  287. package/src/triggers/trigger-runner.js +169 -0
  288. package/src/server/storage/postgres-runtime-store.d.ts +0 -39
@@ -3,8 +3,9 @@ import type { ConnectionError, ConnectionSummary, ManagedConnectionSummary } fro
3
3
  import type { ProviderAuthSetup } from "../../core/provider-setup.ts";
4
4
  import type { ExecutionResult, ProviderScenario } from "../../core/types.ts";
5
5
  import type { OAuthClientConfigSummary } from "../../oauth/oauth-client-config-service.ts";
6
+ import type { TriggerPermission } from "../../triggers/metadata.ts";
6
7
  import type { Context } from "hono";
7
- type RuntimeStatus = 400 | 401 | 402 | 403 | 404 | 409 | 413 | 429 | 500 | 501;
8
+ export type RuntimeStatus = 400 | 401 | 402 | 403 | 404 | 409 | 413 | 429 | 500 | 501 | 502 | 503 | 504;
8
9
  export type RuntimeResponseMeta = Record<string, unknown>;
9
10
  export interface RuntimeSuccessEnvelope<TData> {
10
11
  success: true;
@@ -54,6 +55,7 @@ export interface RuntimeActionMetadata {
54
55
  }
55
56
  export interface RuntimeConnectedApp {
56
57
  id: string;
58
+ providerAccountId: string;
57
59
  service: string;
58
60
  status: "active" | "disconnected";
59
61
  alias: string;
@@ -74,6 +76,9 @@ export interface RuntimeFailureInput {
74
76
  export interface RuntimeActionResultInput {
75
77
  actionId: string;
76
78
  executionId: string;
79
+ remoteExecutionId?: string;
80
+ failureStatus?: RuntimeStatus;
81
+ retryAfter?: string;
77
82
  auditPersisted: boolean;
78
83
  result: ExecutionResult;
79
84
  }
@@ -139,5 +144,8 @@ interface RuntimeOAuthClientSetup {
139
144
  expectedRedirectUri: string;
140
145
  missingFields: string[];
141
146
  }
142
- export declare function serializeRuntimeProviderSetup(provider: RuntimeProviderDefinition, oauth?: OAuthClientConfigSummary): RuntimeProviderSetup;
147
+ export declare function serializeRuntimeProviderSetup(provider: RuntimeProviderDefinition, oauth?: Pick<OAuthClientConfigSummary, "configured" | "customClientAvailable" | "expectedRedirectUri" | "missingFields">): RuntimeProviderSetup;
148
+ export declare function serializeRuntimeTriggerPermissions(provider: RuntimeProviderDefinition): (TriggerPermission & {
149
+ requiredScopes: readonly string[];
150
+ })[];
143
151
  export {};
@@ -1,4 +1,4 @@
1
- import { optionalInteger, optionalRecord, requiredRecord } from "../../core/cast.js";
1
+ import { optionalInteger, optionalString, optionalRecord, requiredRecord } from "../../core/cast.js";
2
2
  import { describeProviderAuth } from "../../core/provider-setup.js";
3
3
  export function serializeRuntimeProvider(provider) {
4
4
  return {
@@ -37,6 +37,7 @@ export function serializeRuntimeAction(action) {
37
37
  export function serializeRuntimeConnectedApp(connection) {
38
38
  return {
39
39
  id: connection.id,
40
+ providerAccountId: connection.profile.accountId,
40
41
  service: connection.service,
41
42
  status: connection.configured ? "active" : "disconnected",
42
43
  alias: connection.connectionName,
@@ -91,7 +92,7 @@ export function serializeRuntimeFailure(input) {
91
92
  /** Build the persistable HTTP response for a completed action execution. */
92
93
  export function serializeRuntimeActionResult(input) {
93
94
  const { actionId, executionId, auditPersisted, result } = input;
94
- const meta = { executionId, actionId, auditPersisted };
95
+ const meta = { executionId, actionId, auditPersisted, remoteExecutionId: input.remoteExecutionId };
95
96
  if (result.ok) {
96
97
  return {
97
98
  status: 200,
@@ -104,10 +105,10 @@ export function serializeRuntimeActionResult(input) {
104
105
  };
105
106
  }
106
107
  return serializeRuntimeFailure({
107
- status: mapExecutionErrorStatus(result.error?.code, result.error?.details),
108
+ status: input.failureStatus ?? mapExecutionErrorStatus(result.error?.code, result.error?.details),
108
109
  errorCode: result.error?.code ?? "provider_error",
109
110
  message: result.error?.message ?? "Action execution failed.",
110
- data: result.error?.details ?? null,
111
+ data: input.retryAfter ? { details: { retryAfter: input.retryAfter } } : (result.error?.details ?? null),
111
112
  meta,
112
113
  });
113
114
  }
@@ -136,6 +137,9 @@ export function parseRuntimeActionHttpResult(value) {
136
137
  * which is what an idempotent replay re-emits the header from.
137
138
  */
138
139
  export function writeRuntimeActionHttpResult(context, result) {
140
+ const retryAfter = optionalString(optionalRecord(optionalRecord(result.body.data)?.details)?.retryAfter);
141
+ if (result.status === 429 && retryAfter && (/^\d+$/.test(retryAfter) || Number.isFinite(Date.parse(retryAfter))))
142
+ context.header("Retry-After", retryAfter);
139
143
  const retryAfterSeconds = readRuntimeRetryAfterSeconds(result);
140
144
  if (retryAfterSeconds !== undefined) {
141
145
  context.header("Retry-After", String(retryAfterSeconds));
@@ -209,6 +213,9 @@ function isRuntimeStatus(value) {
209
213
  value === 409 ||
210
214
  value === 413 ||
211
215
  value === 429 ||
216
+ value === 502 ||
217
+ value === 503 ||
218
+ value === 504 ||
212
219
  value === 500 ||
213
220
  value === 501);
214
221
  }
@@ -249,3 +256,9 @@ export function serializeRuntimeProviderSetup(provider, oauth) {
249
256
  : undefined,
250
257
  };
251
258
  }
259
+ export function serializeRuntimeTriggerPermissions(provider) {
260
+ return (provider.triggerPermissions ?? []).map((permission) => ({
261
+ ...permission,
262
+ requiredScopes: permission.providerPermissions,
263
+ }));
264
+ }
@@ -0,0 +1,2 @@
1
+ /** The initial GET contains no account data and performs no authorization synchronization. */
2
+ export declare function renderSaasCompletionPage(): string;
@@ -0,0 +1,103 @@
1
+ import { oauthCompletionStrings, oauthCompletionStyles, oauthCompletionLocaleScript } from "./oauth-completion-page.js";
2
+ /** The initial GET contains no account data and performs no authorization synchronization. */
3
+ export function renderSaasCompletionPage() {
4
+ return `<!doctype html>
5
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Complete connection</title>
7
+ <style>${oauthCompletionStyles}</style></head>
8
+ <body><main class="card" aria-live="polite">
9
+ <div class="header"><span id="badge" class="badge" hidden></span>
10
+ <h1 id="title">Completing connection</h1><p id="status" role="status">Checking your Console session…</p></div>
11
+ <div class="actions"><a id="login" class="button" href="/" target="_blank" rel="noopener" hidden>Open Console to sign in</a>
12
+ <button id="retry" class="button" type="button">Check again</button>
13
+ <button id="close" class="button" type="button" hidden>Close window</button>
14
+ <p id="note" class="close-note" hidden></p></div></main>
15
+ <script>
16
+ const STR = ${JSON.stringify(oauthCompletionStrings).replaceAll("<", "\\u003c")};
17
+ ${oauthCompletionLocaleScript}
18
+ const language = pick();
19
+ const t = STR[language] || STR.en;
20
+ document.documentElement.lang = language;
21
+ document.title = t.checkingTitle;
22
+ const title = document.getElementById('title');
23
+ const status = document.getElementById('status');
24
+ const login = document.getElementById('login');
25
+ const close = document.getElementById('close');
26
+ const badge = document.getElementById('badge');
27
+ const note = document.getElementById('note');
28
+ title.textContent = t.checkingTitle;
29
+ status.textContent = t.checking;
30
+ login.textContent = t.signIn;
31
+ close.textContent = t.closeButton;
32
+ const tryClose = () => { window.close(); note.textContent = t.manualClose; };
33
+ close.addEventListener('click', tryClose);
34
+ const button = document.getElementById('retry');
35
+ button.textContent = t.retry;
36
+ const request = new URL(location.href).searchParams.get('request');
37
+ let timer;
38
+ let busy = false;
39
+ let terminal = false;
40
+ let failures = 0;
41
+ async function sync() {
42
+ if (busy || terminal) return;
43
+ clearTimeout(timer);
44
+ if (!request) { status.textContent = t.missing; button.hidden = true; return; }
45
+ busy = true;
46
+ button.disabled = true;
47
+ try {
48
+ const session = await fetch('/api/auth/session', { credentials: 'same-origin', cache: 'no-store' });
49
+ if (!session.ok || !(await session.json()).authenticated) {
50
+ status.textContent = t.login; login.hidden = false;
51
+ return;
52
+ }
53
+ login.hidden = true;
54
+ const response = await fetch('/api/oauth/connection-requests/' + encodeURIComponent(request) + '/sync', {
55
+ method: 'POST', credentials: 'same-origin', cache: 'no-store',
56
+ headers: { 'Content-Type': 'application/json', 'X-OpenConnector-Request': 'sync' }, body: '{}'
57
+ });
58
+ if (!response.ok) {
59
+ if ([401, 403, 404].includes(response.status)) { status.textContent = response.status === 401 ? t.login : response.status === 403 ? t.forbidden : t.notFound; login.hidden = response.status !== 401; return; }
60
+ status.textContent = t.retrying;
61
+ const retry = response.headers.get('Retry-After');
62
+ const retryMs = retry ? (/^\\d+$/.test(retry) ? Number(retry) * 1000 : Date.parse(retry) - Date.now()) : 0;
63
+ timer = setTimeout(sync, Math.max(2000, Math.min(30000, 2000 * 2 ** Math.min(failures++, 4)), Number.isFinite(retryMs) ? retryMs : 0));
64
+ return;
65
+ }
66
+ failures = 0;
67
+ const result = await response.json();
68
+ if (result.request.status === 'connected') {
69
+ terminal = true;
70
+ document.title = title.textContent = t.title;
71
+ status.textContent = t.body;
72
+ badge.textContent = t.badge;
73
+ badge.hidden = false;
74
+ button.hidden = true;
75
+ login.hidden = true;
76
+ close.hidden = false;
77
+ const message = { type: 'oauth.completed', service: result.request.service };
78
+ if (typeof BroadcastChannel !== 'undefined') { const channel = new BroadcastChannel('oomol-connect-oauth'); channel.postMessage(message); channel.close(); }
79
+ if (window.opener) window.opener.postMessage(message, location.origin);
80
+ if (result.returnUri) { location.assign(result.returnUri); return; }
81
+ note.hidden = false;
82
+ note.textContent = t.autoClose.replace('%N%', '2');
83
+ setTimeout(tryClose, 2000);
84
+ return;
85
+ }
86
+ if (result.request.status === 'failed' || result.request.status === 'expired') {
87
+ terminal = true;
88
+ status.textContent = result.request.status === 'expired' ? t.notFound : t.failed;
89
+ button.hidden = true;
90
+ close.hidden = false;
91
+ if (result.returnUri) location.assign(result.returnUri);
92
+ return;
93
+ }
94
+ status.textContent = t.waiting;
95
+ timer = setTimeout(sync, 2000);
96
+ } catch {
97
+ status.textContent = t.network;
98
+ } finally { busy = false; button.disabled = false; }
99
+ }
100
+ button.addEventListener('click', sync);
101
+ sync();
102
+ </script></body></html>`;
103
+ }
@@ -7,6 +7,8 @@ import type { ITransitFileService } from "./files/transit-file-store.ts";
7
7
  import type { ISecretCodec } from "./secrets/secret-codec-core.ts";
8
8
  import type { RuntimeDatabase } from "./storage/runtime-database.ts";
9
9
  import type { Hono } from "hono";
10
+ import { SaasCleanupService } from "../saas/saas-cleanup-service.ts";
11
+ import { TriggerMaintenance } from "../triggers/maintenance.ts";
10
12
  export interface ConnectAppOptions {
11
13
  catalog: CatalogStore;
12
14
  providerLoader: IProviderLoader;
@@ -14,6 +16,7 @@ export interface ConnectAppOptions {
14
16
  transitFiles: ITransitFileService;
15
17
  uploadTransitFile?: (request: Request) => Promise<TransitFileUpload>;
16
18
  publicOrigin: string;
19
+ configuredOrigin?: string;
17
20
  secretCodec: ISecretCodec;
18
21
  adminToken?: string;
19
22
  runtimeToken?: string;
@@ -27,6 +30,8 @@ export interface ConnectAppOptions {
27
30
  serveDocumentation?: boolean;
28
31
  }
29
32
  export interface ConnectApp {
33
+ saasCleanup: SaasCleanupService;
34
+ triggerMaintenance: TriggerMaintenance;
30
35
  app: Hono;
31
36
  runtimeAuthConfigured: boolean;
32
37
  }
@@ -1,12 +1,34 @@
1
1
  import { ConnectionService } from "../connection-service.js";
2
+ import { ActionPolicyService as ExecutionPolicyService } from "../core/action-policy.js";
2
3
  import { MarketplaceService } from "../marketplace/marketplace-service.js";
3
4
  import { OAuthClientConfigService } from "../oauth/oauth-client-config-service.js";
4
5
  import { OAuthCredentialRefreshService } from "../oauth/oauth-credential-refresh-service.js";
5
6
  import { OAuthFlowService } from "../oauth/oauth-flow-service.js";
7
+ import { SaasCleanupService } from "../saas/saas-cleanup-service.js";
8
+ import { SaasClient } from "../saas/saas-client.js";
9
+ import { SaasExecutionService } from "../saas/saas-execution-service.js";
10
+ import { SaasOAuthService } from "../saas/saas-oauth-service.js";
11
+ import { SaasProjectService } from "../saas/saas-project-service.js";
12
+ import { TriggerMaintenance } from "../triggers/maintenance.js";
13
+ import { TriggerRunner } from "../triggers/trigger-runner.js";
6
14
  import { ActionRunner } from "./actions/action-runner.js";
7
15
  import { ConnectServer } from "./connect-server.js";
8
16
  import { RuntimeTokenService } from "./storage/runtime-token-service.js";
9
17
  export async function createConnectApp(options) {
18
+ const saasClient = new SaasClient();
19
+ const saasProject = new SaasProjectService({
20
+ catalog: options.catalog,
21
+ store: options.runtimeDatabase.saasProjectStore,
22
+ secretCodec: options.secretCodec,
23
+ configuredOrigin: options.configuredOrigin,
24
+ client: saasClient,
25
+ });
26
+ const saasOAuth = new SaasOAuthService({
27
+ projects: saasProject,
28
+ requests: options.runtimeDatabase.connectionRequestStore,
29
+ client: saasClient,
30
+ });
31
+ const saas = new SaasExecutionService({ projects: saasProject, client: saasClient });
10
32
  const marketplace = new MarketplaceService({
11
33
  catalog: options.catalog,
12
34
  store: options.runtimeDatabase.marketplaceStore,
@@ -36,11 +58,33 @@ export async function createConnectApp(options) {
36
58
  providerLoader: options.providerLoader,
37
59
  connections,
38
60
  runs: options.runtimeDatabase.runLogStore,
61
+ saas,
39
62
  transitFiles: options.transitFiles,
40
63
  logger: options.logger,
41
64
  marketplace,
42
65
  });
66
+ const triggers = new TriggerRunner({
67
+ catalog: options.catalog,
68
+ providerLoader: options.providerLoader,
69
+ connections,
70
+ store: options.runtimeDatabase.triggerStore,
71
+ });
72
+ const triggerMaintenance = new TriggerMaintenance({
73
+ store: options.runtimeDatabase.triggerStore,
74
+ runner: triggers,
75
+ tokens: options.runtimeDatabase.runtimeTokenStore,
76
+ runtimePolicy: options.runtimeDatabase.runtimePolicyStore,
77
+ deploymentPolicy: options.actionPolicy ?? new ExecutionPolicyService(),
78
+ logger: options.logger,
79
+ });
43
80
  return {
81
+ triggerMaintenance,
82
+ saasCleanup: new SaasCleanupService({
83
+ store: options.runtimeDatabase.saasProjectStore,
84
+ requests: options.runtimeDatabase.connectionRequestStore,
85
+ client: saasClient,
86
+ logger: options.logger,
87
+ }),
44
88
  app: new ConnectServer({
45
89
  catalog: options.catalog,
46
90
  publicOrigin: options.publicOrigin,
@@ -55,8 +99,11 @@ export async function createConnectApp(options) {
55
99
  requests: options.runtimeDatabase.connectionRequestStore,
56
100
  secretCodec: options.secretCodec,
57
101
  isCustomClientConfigAllowed,
102
+ saasOAuth,
58
103
  }),
59
104
  actions,
105
+ triggers,
106
+ triggerMaintenance,
60
107
  idempotency: options.runtimeDatabase.idempotencyStore,
61
108
  transitFiles: options.transitFiles,
62
109
  uploadTransitFile: options.uploadTransitFile,
@@ -73,6 +120,9 @@ export async function createConnectApp(options) {
73
120
  actionPolicy: options.actionPolicy,
74
121
  logger: options.logger,
75
122
  marketplace,
123
+ saas,
124
+ saasProject,
125
+ saasOAuth,
76
126
  compressApiResponses: options.compressApiResponses,
77
127
  serveDocumentation: options.serveDocumentation,
78
128
  }).createApp(),
@@ -4,6 +4,11 @@ import type { ActionSearchIndexProvider } from "../core/action-search.ts";
4
4
  import type { RuntimeLogger, TransitFileUpload } from "../core/types.ts";
5
5
  import type { MarketplaceService } from "../marketplace/marketplace-service.ts";
6
6
  import type { IProviderLoader } from "../providers/provider-loader.ts";
7
+ import type { SaasExecutionService } from "../saas/saas-execution-service.ts";
8
+ import type { SaasOAuthService } from "../saas/saas-oauth-service.ts";
9
+ import type { SaasProjectService } from "../saas/saas-project-service.ts";
10
+ import type { TriggerMaintenance } from "../triggers/maintenance.ts";
11
+ import type { TriggerRunner } from "../triggers/trigger-runner.ts";
7
12
  import type { LocalAuthOptions } from "./api/auth.ts";
8
13
  import type { ITransitFileService } from "./files/transit-file-store.ts";
9
14
  import type { IIdempotencyStore } from "./storage/idempotency-store.ts";
@@ -33,6 +38,8 @@ export interface IConnectServerOptions {
33
38
  oauthFlow: OAuthFlowService;
34
39
  runtimeTokens: RuntimeTokenService;
35
40
  actions: ActionRunner;
41
+ triggers?: TriggerRunner;
42
+ triggerMaintenance?: TriggerMaintenance;
36
43
  idempotency: IIdempotencyStore;
37
44
  transitFiles: ITransitFileService;
38
45
  uploadTransitFile?: (request: Request) => Promise<TransitFileUpload>;
@@ -45,6 +52,9 @@ export interface IConnectServerOptions {
45
52
  compressApiResponses?: boolean;
46
53
  serveDocumentation?: boolean;
47
54
  marketplace?: MarketplaceService;
55
+ saasProject?: SaasProjectService;
56
+ saas?: SaasExecutionService;
57
+ saasOAuth?: SaasOAuthService;
48
58
  }
49
59
  /**
50
60
  * Local single-user HTTP server for catalog browsing, credential management,
@@ -78,6 +88,8 @@ export declare class ConnectServer {
78
88
  private searchRuntimeActions;
79
89
  private serializeSearchResults;
80
90
  private getRuntimeAction;
91
+ private getRuntimeTriggerPermissions;
92
+ private executeRuntimeTrigger;
81
93
  private createRuntimeActionRun;
82
94
  private executeRuntimeAction;
83
95
  private createRuntimeProxyRequest;