@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.
- package/README.md +4 -0
- package/assets/open-connector/catalog/apps/airtable.json +134 -0
- package/assets/open-connector/catalog/apps/aisa.json +6985 -319
- package/assets/open-connector/catalog/apps/baizhi_mcp.json +135 -0
- package/assets/open-connector/catalog/apps/cal.json +24 -6
- package/assets/open-connector/catalog/apps/discordbot.json +2888 -248
- package/assets/open-connector/catalog/apps/drawio_mcp.json +192 -0
- package/assets/open-connector/catalog/apps/enormail.json +411 -0
- package/assets/open-connector/catalog/apps/feishu_app_bot.json +158 -0
- package/assets/open-connector/catalog/apps/firecrawl.json +176 -32
- package/assets/open-connector/catalog/apps/framejet.json +273 -0
- package/assets/open-connector/catalog/apps/futunn.json +2967 -0
- package/assets/open-connector/catalog/apps/github.json +275 -0
- package/assets/open-connector/catalog/apps/gitlab.json +125 -0
- package/assets/open-connector/catalog/apps/gmail.json +376 -0
- package/assets/open-connector/catalog/apps/google_analytics.json +4 -1
- package/assets/open-connector/catalog/apps/google_bigquery.json +4 -1
- package/assets/open-connector/catalog/apps/google_search_console.json +4 -1
- package/assets/open-connector/catalog/apps/googlecalendar.json +210 -1
- package/assets/open-connector/catalog/apps/googlechat.json +694 -7
- package/assets/open-connector/catalog/apps/googledocs.json +4 -1
- package/assets/open-connector/catalog/apps/googledrive.json +479 -0
- package/assets/open-connector/catalog/apps/googlesheets.json +148 -1
- package/assets/open-connector/catalog/apps/granola.json +23 -0
- package/assets/open-connector/catalog/apps/hithink_finance.json +6 -3
- package/assets/open-connector/catalog/apps/indexed.json +1115 -0
- package/assets/open-connector/catalog/apps/keepa.json +3534 -987
- package/assets/open-connector/catalog/apps/linear.json +133 -0
- package/assets/open-connector/catalog/apps/linear_mcp.json +510 -0
- package/assets/open-connector/catalog/apps/moneyforward_mcp.json +1432 -0
- package/assets/open-connector/catalog/apps/notion.json +588 -1
- package/assets/open-connector/catalog/apps/notion_mcp.json +490 -0
- package/assets/open-connector/catalog/apps/odoo.json +619 -0
- package/assets/open-connector/catalog/apps/one_drive.json +185 -0
- package/assets/open-connector/catalog/apps/outlook.json +212 -8
- package/assets/open-connector/catalog/apps/outlook_calendar.json +23 -2
- package/assets/open-connector/catalog/apps/postiz.json +334 -0
- package/assets/open-connector/catalog/apps/proworkflow.json +529 -0
- package/assets/open-connector/catalog/apps/sellersprite_mcp.json +2 -1
- package/assets/open-connector/catalog/apps/shopify.json +282 -0
- package/assets/open-connector/catalog/apps/slack.json +405 -0
- package/assets/open-connector/catalog/apps/slackbot.json +214 -0
- package/assets/open-connector/catalog/apps/spotify.json +46 -43
- package/assets/open-connector/catalog/apps/stripe.json +96 -0
- package/assets/open-connector/catalog/apps/telegram.json +138 -0
- package/assets/open-connector/catalog/apps/tencent_docs.json +3 -0
- package/assets/open-connector/catalog/apps/weixin_store.json +543 -2
- package/assets/open-connector/catalog/apps/wisburg.json +1528 -0
- package/assets/open-connector/catalog/apps/woocommerce.json +127 -0
- package/assets/open-connector/catalog/apps/youtube.json +4 -1
- package/assets/open-connector/catalog/apps/zendesk.json +152 -0
- package/assets/open-connector/catalog/apps/zerotier.json +3319 -0
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/assets/open-connector/migrations/0014_saas_project.sql +55 -0
- package/assets/open-connector/migrations/0015_saas_cleanup_runtime.sql +8 -0
- package/assets/open-connector/migrations/0016_trigger_policy.sql +1 -0
- package/assets/open-connector/migrations/0017_trigger_subscriptions.sql +17 -0
- package/assets/open-connector/migrations/postgresql/0014_saas_project.sql +55 -0
- package/assets/open-connector/migrations/postgresql/0015_saas_cleanup_runtime.sql +8 -0
- package/assets/open-connector/migrations/postgresql/0016_trigger_policy.sql +1 -0
- package/assets/open-connector/migrations/postgresql/0017_trigger_subscriptions.sql +17 -0
- package/package.json +2 -2
- package/src/connection-service.d.ts +40 -7
- package/src/connection-service.js +60 -18
- package/src/core/action-policy.d.ts +8 -1
- package/src/core/action-policy.js +51 -0
- package/src/core/cast.d.ts +13 -0
- package/src/core/cast.js +18 -1
- package/src/core/guarded-fetch.d.ts +11 -3
- package/src/core/guarded-fetch.js +19 -7
- package/src/core/provider-scenarios.js +67 -13
- package/src/core/remote-http.d.ts +33 -0
- package/src/core/remote-http.js +104 -0
- package/src/core/request.d.ts +1 -0
- package/src/core/request.js +11 -1
- package/src/core/types.d.ts +5 -1
- package/src/marketplace/marketplace-service.d.ts +0 -1
- package/src/marketplace/marketplace-service.js +80 -92
- package/src/mcp.js +26 -9
- package/src/oauth/oauth-client-config-service.d.ts +16 -1
- package/src/oauth/oauth-client-config-service.js +59 -3
- package/src/oauth/oauth-flow-service.d.ts +14 -1
- package/src/oauth/oauth-flow-service.js +14 -6
- package/src/providers/17track/runtime.js +1 -1
- package/src/providers/action-contracts.generated.d.ts +20 -6
- package/src/providers/aifinmarket/runtime.js +1 -1
- package/src/providers/airtable/executors.d.ts +3 -0
- package/src/providers/airtable/executors.js +2 -0
- package/src/providers/airtable/trigger-on-record-changed.d.ts +2 -0
- package/src/providers/airtable/trigger-on-record-changed.definition.d.ts +4 -0
- package/src/providers/airtable/trigger-on-record-changed.definition.js +54 -0
- package/src/providers/airtable/trigger-on-record-changed.js +235 -0
- package/src/providers/aisa/executors.js +912 -50
- package/src/providers/aliyun_ack/runtime.js +1 -1
- package/src/providers/aliyun_sls/runtime.js +1 -1
- package/src/providers/app_store_server/runtime-helpers.js +1 -1
- package/src/providers/baizhi_mcp/actions.d.ts +2 -0
- package/src/providers/baizhi_mcp/actions.js +40 -0
- package/src/providers/baizhi_mcp/executors.d.ts +3 -0
- package/src/providers/baizhi_mcp/executors.js +102 -0
- package/src/providers/bazhuayu/runtime.js +2 -2
- package/src/providers/bilibili/runtime.js +2 -4
- package/src/providers/bilibili/upload.js +9 -7
- package/src/providers/cal/actions.js +5 -1
- package/src/providers/cloudflare_browser_rendering/executors.js +1 -1
- package/src/providers/cloudflare_dns/executors.js +1 -1
- package/src/providers/{cloudflare-current-user.js → cloudflare_dns/runtime-user.js} +2 -2
- package/src/providers/cloudflare_dns/runtime.d.ts +1 -1
- package/src/providers/cloudflare_dns/runtime.js +1 -1
- package/src/providers/cloudflare_r2/executors.js +1 -1
- package/src/providers/cloudflare_r2/runtime.d.ts +1 -1
- package/src/providers/cloudflare_r2/runtime.js +1 -1
- package/src/providers/cloudflare_worker/executors.js +1 -1
- package/src/providers/cloudflare_worker/runtime.d.ts +1 -1
- package/src/providers/cloudflare_worker/runtime.js +1 -1
- package/src/providers/dingtalk_mcp/runtime.js +1 -1
- package/src/providers/discordbot/executors.d.ts +0 -9
- package/src/providers/discordbot/executors.js +9 -101
- package/src/providers/discordbot/runtime-guilds.d.ts +3 -0
- package/src/providers/discordbot/runtime-guilds.js +464 -0
- package/src/providers/discordbot/runtime.d.ts +42 -0
- package/src/providers/discordbot/runtime.js +124 -0
- package/src/providers/drawio_mcp/executors.d.ts +3 -0
- package/src/providers/drawio_mcp/executors.js +19 -0
- package/src/providers/drawio_mcp/runtime.d.ts +8 -0
- package/src/providers/drawio_mcp/runtime.js +175 -0
- package/src/providers/enormail/executors.d.ts +4 -0
- package/src/providers/enormail/executors.js +97 -0
- package/src/providers/fastmoss_mcp/executors.js +2 -2
- package/src/providers/feishu_app_bot/executors.d.ts +3 -0
- package/src/providers/feishu_app_bot/executors.js +2 -0
- package/src/providers/feishu_app_bot/trigger-config.d.ts +1 -0
- package/src/providers/feishu_app_bot/trigger-config.js +10 -0
- package/src/providers/feishu_app_bot/trigger-on-event.d.ts +2 -0
- package/src/providers/feishu_app_bot/trigger-on-event.definition.d.ts +4 -0
- package/src/providers/feishu_app_bot/trigger-on-event.definition.js +63 -0
- package/src/providers/feishu_app_bot/trigger-on-event.js +29 -0
- package/src/providers/feishu_app_bot/trigger-subscriptions.d.ts +5 -0
- package/src/providers/feishu_app_bot/trigger-subscriptions.js +70 -0
- package/src/providers/finchina/executors.js +1 -1
- package/src/providers/framejet/executors.d.ts +4 -0
- package/src/providers/framejet/executors.js +19 -0
- package/src/providers/framejet/runtime.d.ts +16 -0
- package/src/providers/framejet/runtime.js +148 -0
- package/src/providers/futunn/actions.d.ts +2 -0
- package/src/providers/futunn/actions.js +152 -0
- package/src/providers/futunn/actions.research.d.ts +2 -0
- package/src/providers/futunn/actions.research.js +423 -0
- package/src/providers/futunn/actions.trading.d.ts +2 -0
- package/src/providers/futunn/actions.trading.js +204 -0
- package/src/providers/futunn/executors.d.ts +3 -0
- package/src/providers/futunn/executors.js +24 -0
- package/src/providers/futunn/runtime-research.d.ts +3 -0
- package/src/providers/futunn/runtime-research.js +133 -0
- package/src/providers/futunn/runtime-trading.d.ts +3 -0
- package/src/providers/futunn/runtime-trading.js +39 -0
- package/src/providers/futunn/runtime.d.ts +2 -0
- package/src/providers/futunn/runtime.js +50 -0
- package/src/providers/futunn/transport.d.ts +11 -0
- package/src/providers/futunn/transport.js +76 -0
- package/src/providers/gildata/executors.js +1 -1
- package/src/providers/github/executors.d.ts +3 -0
- package/src/providers/github/executors.js +6 -0
- package/src/providers/github/trigger-on-repo-event.d.ts +2 -0
- package/src/providers/github/trigger-on-repo-event.definition.d.ts +4 -0
- package/src/providers/github/trigger-on-repo-event.definition.js +94 -0
- package/src/providers/github/trigger-on-repo-event.js +168 -0
- package/src/providers/github/trigger-watch-pull-request.d.ts +2 -0
- package/src/providers/github/trigger-watch-pull-request.definition.d.ts +4 -0
- package/src/providers/github/trigger-watch-pull-request.definition.js +49 -0
- package/src/providers/github/trigger-watch-pull-request.js +106 -0
- package/src/providers/gitlab/executors.d.ts +3 -0
- package/src/providers/gitlab/executors.js +2 -0
- package/src/providers/gitlab/trigger-on-project-event.d.ts +2 -0
- package/src/providers/gitlab/trigger-on-project-event.definition.d.ts +5 -0
- package/src/providers/gitlab/trigger-on-project-event.definition.js +63 -0
- package/src/providers/gitlab/trigger-on-project-event.js +186 -0
- package/src/providers/gmail/executors.d.ts +3 -0
- package/src/providers/gmail/executors.js +5 -3
- package/src/providers/gmail/message.d.ts +6 -8
- package/src/providers/gmail/message.js +4 -0
- package/src/providers/gmail/scopes.d.ts +32 -0
- package/src/providers/gmail/scopes.js +37 -0
- package/src/providers/gmail/trigger-on-message-received.d.ts +2 -0
- package/src/providers/gmail/trigger-on-message-received.definition.d.ts +4 -0
- package/src/providers/gmail/trigger-on-message-received.definition.js +74 -0
- package/src/providers/gmail/trigger-on-message-received.js +232 -0
- package/src/providers/google_analytics/executors.js +2 -2
- package/src/providers/google_analytics/scopes.js +6 -1
- package/src/providers/google_bigquery/executors.js +2 -2
- package/src/providers/google_bigquery/scopes.js +2 -0
- package/src/providers/google_search_console/executors.js +2 -2
- package/src/providers/google_search_console/scopes.js +2 -0
- package/src/providers/googleads/executors.js +1 -1
- package/src/providers/googleads/scopes.d.ts +1 -3
- package/src/providers/googleads/scopes.js +2 -4
- package/src/providers/googlecalendar/executors.d.ts +3 -0
- package/src/providers/googlecalendar/executors.js +3 -1
- package/src/providers/googlecalendar/runtime-shared.js +2 -2
- package/src/providers/googlecalendar/scopes.js +2 -0
- package/src/providers/googlecalendar/trigger-on-event-changed.d.ts +2 -0
- package/src/providers/googlecalendar/trigger-on-event-changed.definition.d.ts +4 -0
- package/src/providers/googlecalendar/trigger-on-event-changed.definition.js +74 -0
- package/src/providers/googlecalendar/trigger-on-event-changed.js +233 -0
- package/src/providers/googlechat/executors.d.ts +1 -3
- package/src/providers/googlechat/executors.js +219 -28
- package/src/providers/googlechat/members.d.ts +55 -0
- package/src/providers/googlechat/members.js +293 -0
- package/src/providers/googlechat/runtime.d.ts +16 -0
- package/src/providers/googlechat/runtime.js +25 -0
- package/src/providers/googlechat/scopes.d.ts +22 -3
- package/src/providers/googlechat/scopes.js +30 -7
- package/src/providers/googledocs/executors.js +1 -1
- package/src/providers/googledrive/executors.d.ts +3 -0
- package/src/providers/googledrive/executors.js +9 -2
- package/src/providers/{google-auth.d.ts → googledrive/runtime-auth.d.ts} +2 -2
- package/src/providers/{google-auth.js → googledrive/runtime-auth.js} +3 -3
- package/src/providers/googledrive/runtime-collaboration.js +1 -1
- package/src/providers/{google-runtime.d.ts → googledrive/runtime-request.d.ts} +1 -1
- package/src/providers/{google-runtime.js → googledrive/runtime-request.js} +2 -2
- package/src/providers/googledrive/trigger-changes.d.ts +12 -0
- package/src/providers/googledrive/trigger-changes.definition.d.ts +7 -0
- package/src/providers/googledrive/trigger-changes.definition.js +101 -0
- package/src/providers/googledrive/trigger-changes.js +452 -0
- package/src/providers/googledrive/trigger-on-file-change.d.ts +2 -0
- package/src/providers/googledrive/trigger-on-file-change.definition.d.ts +4 -0
- package/src/providers/googledrive/trigger-on-file-change.definition.js +77 -0
- package/src/providers/googledrive/trigger-on-file-change.js +258 -0
- package/src/providers/googleforms/executors.js +2 -2
- package/src/providers/googleforms/scopes.d.ts +0 -3
- package/src/providers/googleforms/scopes.js +2 -6
- package/src/providers/googlemeet/executors.js +2 -2
- package/src/providers/googlemeet/scopes.d.ts +0 -3
- package/src/providers/googlemeet/scopes.js +2 -6
- package/src/providers/googlesheets/executors.d.ts +3 -0
- package/src/providers/googlesheets/executors.js +3 -1
- package/src/providers/googlesheets/scopes.js +2 -0
- package/src/providers/googlesheets/trigger-on-row-added.d.ts +2 -0
- package/src/providers/googlesheets/trigger-on-row-added.definition.d.ts +4 -0
- package/src/providers/googlesheets/trigger-on-row-added.definition.js +54 -0
- package/src/providers/googlesheets/trigger-on-row-added.js +234 -0
- package/src/providers/googleslides/executors.js +2 -2
- package/src/providers/googleslides/scopes.d.ts +0 -3
- package/src/providers/googleslides/scopes.js +2 -6
- package/src/providers/googletasks/executors.js +2 -2
- package/src/providers/googletasks/scopes.d.ts +0 -3
- package/src/providers/googletasks/scopes.js +2 -6
- package/src/providers/granola/actions.js +2 -0
- package/src/providers/granola/runtime-mcp.js +2 -0
- package/src/providers/granola/runtime.js +2 -2
- package/src/providers/hithink_finance/runtime.js +1 -1
- package/src/providers/indexed/executors.d.ts +4 -0
- package/src/providers/indexed/executors.js +16 -0
- package/src/providers/indexed/runtime.d.ts +26 -0
- package/src/providers/indexed/runtime.js +129 -0
- package/src/providers/indiegogo/executors.js +1 -1
- package/src/providers/investoday_mcp/executors.js +2 -2
- package/src/providers/iyunbiao/runtime.js +2 -2
- package/src/providers/keepa/actions.d.ts +1 -1
- package/src/providers/keepa/actions.js +371 -149
- package/src/providers/keepa/deal-attributes.d.ts +1 -0
- package/src/providers/keepa/deal-attributes.js +26 -0
- package/src/providers/keepa/runtime.js +212 -18
- package/src/providers/kingdee/executors.js +1 -1
- package/src/providers/kingdee/runtime.js +2 -2
- package/src/providers/kuaidi100/runtime.js +1 -1
- package/src/providers/linear/executors.d.ts +3 -0
- package/src/providers/linear/executors.js +14 -9
- package/src/providers/linear/trigger-on-issue-changed.d.ts +2 -0
- package/src/providers/linear/trigger-on-issue-changed.definition.d.ts +5 -0
- package/src/providers/linear/trigger-on-issue-changed.definition.js +43 -0
- package/src/providers/linear/trigger-on-issue-changed.js +215 -0
- package/src/providers/linear_mcp/actions.d.ts +47 -0
- package/src/providers/linear_mcp/actions.js +102 -0
- package/src/providers/linear_mcp/endpoints.d.ts +3 -0
- package/src/providers/linear_mcp/endpoints.js +3 -0
- package/src/providers/linear_mcp/executors.d.ts +3 -0
- package/src/providers/linear_mcp/executors.js +9 -0
- package/src/providers/linear_mcp/runtime-mcp.d.ts +15 -0
- package/src/providers/linear_mcp/runtime-mcp.js +238 -0
- package/src/providers/lingxing_mcp/runtime.js +1 -1
- package/src/providers/mcdonalds_cn_mcp/runtime.js +1 -1
- package/src/providers/metabase/mcp-runtime.js +1 -1
- package/src/providers/moneyforward_mcp/executors.d.ts +3 -0
- package/src/providers/moneyforward_mcp/executors.js +11 -0
- package/src/providers/moneyforward_mcp/manifest.d.ts +31 -0
- package/src/providers/moneyforward_mcp/manifest.js +204 -0
- package/src/providers/moneyforward_mcp/runtime.d.ts +18 -0
- package/src/providers/moneyforward_mcp/runtime.js +296 -0
- package/src/providers/notion/executors.d.ts +3 -0
- package/src/providers/notion/executors.js +41 -3
- package/src/providers/notion/trigger-on-database-page-event.d.ts +2 -0
- package/src/providers/notion/trigger-on-database-page-event.definition.d.ts +4 -0
- package/src/providers/notion/trigger-on-database-page-event.definition.js +63 -0
- package/src/providers/notion/trigger-on-database-page-event.js +293 -0
- package/src/providers/notion_mcp/endpoints.d.ts +3 -0
- package/src/providers/notion_mcp/endpoints.js +3 -0
- package/src/providers/notion_mcp/executors.d.ts +3 -0
- package/src/providers/notion_mcp/executors.js +176 -0
- package/src/providers/notion_mcp/mcp-response.d.ts +86 -0
- package/src/providers/notion_mcp/mcp-response.js +314 -0
- package/src/providers/odoo/executors.d.ts +3 -0
- package/src/providers/odoo/executors.js +32 -0
- package/src/providers/odoo/runtime.d.ts +16 -0
- package/src/providers/odoo/runtime.js +140 -0
- package/src/providers/one_drive/executors.d.ts +3 -0
- package/src/providers/one_drive/executors.js +2 -0
- package/src/providers/one_drive/trigger-on-item-changed.d.ts +2 -0
- package/src/providers/one_drive/trigger-on-item-changed.definition.d.ts +4 -0
- package/src/providers/one_drive/trigger-on-item-changed.definition.js +63 -0
- package/src/providers/one_drive/trigger-on-item-changed.js +214 -0
- package/src/providers/outlook/executors.d.ts +3 -0
- package/src/providers/outlook/executors.js +29 -6
- package/src/providers/outlook/microsoft-graph.js +17 -6
- package/src/providers/outlook/trigger-on-message-received.d.ts +2 -0
- package/src/providers/outlook/trigger-on-message-received.definition.d.ts +4 -0
- package/src/providers/outlook/trigger-on-message-received.definition.js +93 -0
- package/src/providers/outlook/trigger-on-message-received.js +226 -0
- package/src/providers/outlook_calendar/executors.js +30 -7
- package/src/providers/patsnap_mcp/executors.js +2 -2
- package/src/providers/postiz/executors.d.ts +4 -0
- package/src/providers/postiz/executors.js +83 -0
- package/src/providers/provider-loader.d.ts +5 -0
- package/src/providers/provider-loader.js +4 -0
- package/src/providers/provider-runtime.d.ts +15 -0
- package/src/providers/provider-runtime.js +57 -4
- package/src/providers/proworkflow/executors.d.ts +4 -0
- package/src/providers/proworkflow/executors.js +135 -0
- package/src/providers/registry.generated.js +14 -0
- package/src/providers/scrape_creators/catalog.js +1 -1
- package/src/providers/scrape_creators/runtime.js +1 -1
- package/src/providers/sellersprite_mcp/executors.js +2 -2
- package/src/providers/sellersprite_mcp/official-actions.js +3 -2
- package/src/providers/sentry/runtime.js +6 -7
- package/src/providers/shopify/executors.d.ts +3 -0
- package/src/providers/shopify/executors.js +2 -0
- package/src/providers/shopify/trigger-on-shop-event.d.ts +2 -0
- package/src/providers/shopify/trigger-on-shop-event.definition.d.ts +4 -0
- package/src/providers/shopify/trigger-on-shop-event.definition.js +214 -0
- package/src/providers/shopify/trigger-on-shop-event.js +165 -0
- package/src/providers/slack/actions.js +52 -3
- package/src/providers/slack/executors.d.ts +3 -0
- package/src/providers/slack/executors.js +2 -0
- package/src/providers/slack/runtime.js +58 -21
- package/src/providers/slack/trigger-on-message-posted.d.ts +2 -0
- package/src/providers/slack/trigger-on-message-posted.definition.d.ts +4 -0
- package/src/providers/slack/trigger-on-message-posted.definition.js +80 -0
- package/src/providers/slack/trigger-on-message-posted.js +176 -0
- package/src/providers/slickdeals/runtime.js +1 -1
- package/src/providers/sorftime_mcp/executors.js +2 -2
- package/src/providers/spotify/runtime.js +15 -4
- package/src/providers/stripe/executors.d.ts +3 -0
- package/src/providers/stripe/executors.js +2 -0
- package/src/providers/stripe/trigger-on-event.d.ts +2 -0
- package/src/providers/stripe/trigger-on-event.definition.d.ts +4 -0
- package/src/providers/stripe/trigger-on-event.definition.js +43 -0
- package/src/providers/stripe/trigger-on-event.js +212 -0
- package/src/providers/telegram/executors.d.ts +3 -0
- package/src/providers/telegram/executors.js +2 -0
- package/src/providers/telegram/trigger-on-update.d.ts +2 -0
- package/src/providers/telegram/trigger-on-update.definition.d.ts +5 -0
- package/src/providers/telegram/trigger-on-update.definition.js +78 -0
- package/src/providers/telegram/trigger-on-update.js +141 -0
- package/src/providers/tikhub/bounded-response.d.ts +1 -1
- package/src/providers/tikhub/bounded-response.js +8 -34
- package/src/providers/tikhub/endpoint-catalog.js +1 -1
- package/src/providers/tikhub/runtime.js +2 -2
- package/src/providers/tongdaxin/executors.js +79 -15
- package/src/providers/uspto/executors.js +1 -1
- package/src/providers/waffo/executors.js +1 -1
- package/src/providers/waffo/runtime.js +1 -1
- package/src/providers/wecom_mcp/runtime.js +1 -1
- package/src/providers/weixin_store/access-token.d.ts +2 -1
- package/src/providers/weixin_store/access-token.js +15 -4
- package/src/providers/weixin_store/executors.js +97 -12
- package/src/providers/wisburg/executors.d.ts +4 -0
- package/src/providers/wisburg/executors.js +13 -0
- package/src/providers/wisburg/runtime.d.ts +12 -0
- package/src/providers/wisburg/runtime.js +133 -0
- package/src/providers/woocommerce/executors.d.ts +3 -0
- package/src/providers/woocommerce/executors.js +2 -0
- package/src/providers/woocommerce/trigger-on-store-event.d.ts +2 -0
- package/src/providers/woocommerce/trigger-on-store-event.definition.d.ts +4 -0
- package/src/providers/woocommerce/trigger-on-store-event.definition.js +55 -0
- package/src/providers/woocommerce/trigger-on-store-event.js +179 -0
- package/src/providers/xydc_mcp/executors.js +2 -2
- package/src/providers/youtube/executors.js +1 -1
- package/src/providers/youtube/runtime.js +1 -1
- package/src/providers/zendesk/executors.d.ts +3 -0
- package/src/providers/zendesk/executors.js +2 -0
- package/src/providers/zendesk/trigger-on-event.d.ts +2 -0
- package/src/providers/zendesk/trigger-on-event.definition.d.ts +5 -0
- package/src/providers/zendesk/trigger-on-event.definition.js +101 -0
- package/src/providers/zendesk/trigger-on-event.js +188 -0
- package/src/providers/zerotier/executors.d.ts +9 -0
- package/src/providers/zerotier/executors.js +629 -0
- package/src/providers/zerotier/runtime.d.ts +54 -0
- package/src/providers/zerotier/runtime.js +207 -0
- package/src/saas/saas-cleanup-service.d.ts +26 -0
- package/src/saas/saas-cleanup-service.js +124 -0
- package/src/saas/saas-client.d.ts +86 -0
- package/src/saas/saas-client.js +369 -0
- package/src/saas/saas-execution-service.d.ts +15 -0
- package/src/saas/saas-execution-service.js +21 -0
- package/src/saas/saas-oauth-service.d.ts +25 -0
- package/src/saas/saas-oauth-service.js +197 -0
- package/src/saas/saas-project-service.d.ts +61 -0
- package/src/saas/saas-project-service.js +211 -0
- package/src/server/actions/action-idempotency.d.ts +1 -0
- package/src/server/actions/action-idempotency.js +1 -0
- package/src/server/actions/action-runner.d.ts +7 -0
- package/src/server/actions/action-runner.js +43 -7
- package/src/server/actions/run-log-summary.js +9 -0
- package/src/server/api/auth.d.ts +1 -0
- package/src/server/api/auth.js +13 -2
- package/src/server/api/cache-policy.js +4 -1
- package/src/server/api/connection-input.d.ts +7 -1
- package/src/server/api/connection-input.js +7 -1
- package/src/server/api/connection-routes.d.ts +3 -1
- package/src/server/api/connection-routes.js +21 -3
- package/src/server/api/http-utils.d.ts +4 -3
- package/src/server/api/oauth-completion-page.d.ts +124 -0
- package/src/server/api/oauth-completion-page.js +113 -18
- package/src/server/api/openapi.js +123 -15
- package/src/server/api/policy-input.js +6 -0
- package/src/server/api/runtime-api.d.ts +18 -3
- package/src/server/api/runtime-api.js +36 -5
- package/src/server/api/saas-completion-page.d.ts +2 -0
- package/src/server/api/saas-completion-page.js +103 -0
- package/src/server/connect-app.d.ts +5 -0
- package/src/server/connect-app.js +50 -0
- package/src/server/connect-server.d.ts +12 -0
- package/src/server/connect-server.js +157 -15
- package/src/server/connector-runtime.d.ts +3 -1
- package/src/server/connector-runtime.js +5 -2
- package/src/server/files/transit-files.js +16 -7
- package/src/server/proxy/proxy-runner.d.ts +5 -1
- package/src/server/proxy/proxy-runner.js +72 -26
- package/src/server/storage/connection-request-store.d.ts +41 -1
- package/src/server/storage/connection-request-store.js +245 -20
- package/src/server/storage/connection-store.d.ts +16 -0
- package/src/server/storage/connection-store.js +119 -0
- package/src/server/storage/node-runtime-database.js +3 -3
- package/src/server/storage/{postgres-migrations.d.ts → postgres/migrations.d.ts} +2 -2
- package/src/server/storage/{postgres-migrations.js → postgres/migrations.js} +1 -1
- package/src/server/storage/postgres/runtime-store.d.ts +43 -0
- package/src/server/storage/{postgres-runtime-store.js → postgres/runtime-store.js} +59 -94
- package/src/server/storage/runtime-database.d.ts +4 -0
- package/src/server/storage/runtime-sql.d.ts +1 -1
- package/src/server/storage/runtime-sql.js +2 -1
- package/src/server/storage/runtime-store.d.ts +1 -0
- package/src/server/storage/runtime-token-service.d.ts +2 -0
- package/src/server/storage/runtime-token-service.js +3 -0
- package/src/server/storage/saas-project-store.d.ts +77 -0
- package/src/server/storage/saas-project-store.js +273 -0
- package/src/server/storage/{sqlite-runtime-store.d.ts → sqlite/runtime-store.d.ts} +21 -25
- package/src/server/storage/{sqlite-runtime-store.js → sqlite/runtime-store.js} +100 -115
- package/src/server/storage/trigger-store.d.ts +16 -0
- package/src/server/storage/trigger-store.js +96 -0
- package/src/triggers/common/config.d.ts +2 -0
- package/src/triggers/common/config.js +17 -0
- package/src/triggers/common/configOptions.d.ts +13 -0
- package/src/triggers/common/configOptions.js +1 -0
- package/src/triggers/common/encoding.d.ts +3 -0
- package/src/triggers/common/encoding.js +19 -0
- package/src/triggers/common/integration.d.ts +115 -0
- package/src/triggers/common/integration.js +31 -0
- package/src/triggers/common/json.d.ts +6 -0
- package/src/triggers/common/json.js +91 -0
- package/src/triggers/common/poll.d.ts +41 -0
- package/src/triggers/common/poll.js +15 -0
- package/src/triggers/common/proxy.d.ts +14 -0
- package/src/triggers/common/proxy.js +1 -0
- package/src/triggers/common/types.d.ts +42 -0
- package/src/triggers/common/types.js +1 -0
- package/src/triggers/maintenance.d.ts +40 -0
- package/src/triggers/maintenance.js +120 -0
- package/src/triggers/metadata.d.ts +8 -0
- package/src/triggers/metadata.js +1 -0
- package/src/triggers/request.d.ts +33 -0
- package/src/triggers/request.js +52 -0
- package/src/triggers/resources.d.ts +12 -0
- package/src/triggers/resources.js +121 -0
- package/src/triggers/signature.d.ts +4 -0
- package/src/triggers/signature.js +48 -0
- package/src/triggers/store.d.ts +29 -0
- package/src/triggers/store.js +1 -0
- package/src/triggers/subscriptions.d.ts +22 -0
- package/src/triggers/subscriptions.js +220 -0
- package/src/triggers/trigger-runner.d.ts +34 -0
- package/src/triggers/trigger-runner.js +169 -0
- package/src/providers/sentry/scopes.d.ts +0 -1
- package/src/providers/sentry/scopes.js +0 -7
- package/src/server/storage/postgres-runtime-store.d.ts +0 -39
- /package/src/providers/{cloudflare-current-user.d.ts → cloudflare_dns/runtime-user.d.ts} +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { canonicalJsonBytes, digestBytes } from "../../triggers/common/encoding.js";
|
|
2
|
+
import { eventsPollOutputs, maximumPollEventsPerPage, PermanentPollError, PollConnectionError, TransientPollError, } from "../../triggers/common/poll.js";
|
|
3
|
+
import { snapshot } from "./trigger-on-item-changed.definition.js";
|
|
4
|
+
export const oneDriveItemChanged = {
|
|
5
|
+
buildOutputs: eventsPollOutputs,
|
|
6
|
+
snapshot,
|
|
7
|
+
async poll(context) {
|
|
8
|
+
const config = resolveConfig(context.config);
|
|
9
|
+
if (context.checkpoint === null)
|
|
10
|
+
return { checkpoint: (await seed(context, config)), events: [] };
|
|
11
|
+
const checkpoint = readCheckpoint(context.checkpoint);
|
|
12
|
+
const { items, next } = await changedItems(context, checkpoint, config.maxItemsPerPoll);
|
|
13
|
+
const events = [];
|
|
14
|
+
let filtered = 0;
|
|
15
|
+
for (const [id, item] of items) {
|
|
16
|
+
const result = await evaluate(id, item, config, checkpoint);
|
|
17
|
+
if (result == "structural")
|
|
18
|
+
continue;
|
|
19
|
+
if (result == "filtered")
|
|
20
|
+
filtered += 1;
|
|
21
|
+
else
|
|
22
|
+
events.push(result);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
checkpoint: next.checkpoint,
|
|
26
|
+
events,
|
|
27
|
+
filtered,
|
|
28
|
+
...(next.hasMore ? { hasMore: true } : {}),
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
function resolveConfig(value) {
|
|
33
|
+
return {
|
|
34
|
+
events: value.events,
|
|
35
|
+
itemId: value.itemId.trim(),
|
|
36
|
+
itemTypes: value.itemTypes,
|
|
37
|
+
maxItemsPerPoll: value.maxItemsPerPoll,
|
|
38
|
+
parentFolderId: value.parentFolderId.trim(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function seed(context, config) {
|
|
42
|
+
const result = await get(context, "/me/drive/root/delta", { token: "latest" });
|
|
43
|
+
if (result.status == 404)
|
|
44
|
+
throw new PermanentPollError("OneDrive is not provisioned for this account.");
|
|
45
|
+
success(result, "delta seeding");
|
|
46
|
+
const link = record(result.data)?.["@odata.deltaLink"];
|
|
47
|
+
const token = link == null ? null : parseToken(link);
|
|
48
|
+
if (token == null)
|
|
49
|
+
throw new TransientPollError("OneDrive delta seeding response has no delta token.");
|
|
50
|
+
await validateItem(context, "parentFolderId", config.parentFolderId);
|
|
51
|
+
await validateItem(context, "itemId", config.itemId);
|
|
52
|
+
return { deltaToken: token, lastPolledAt: context.now.toISOString() };
|
|
53
|
+
}
|
|
54
|
+
async function validateItem(context, field, id) {
|
|
55
|
+
if (id.length == 0)
|
|
56
|
+
return;
|
|
57
|
+
const result = await get(context, `/me/drive/items/${encodeURIComponent(id)}`, {});
|
|
58
|
+
if (result.status == 400 || result.status == 404)
|
|
59
|
+
throw new PermanentPollError(`OneDrive ${field} does not identify an item in this drive.`);
|
|
60
|
+
success(result, `${field} validation`);
|
|
61
|
+
}
|
|
62
|
+
function readCheckpoint(value) {
|
|
63
|
+
const checkpoint = record(value);
|
|
64
|
+
if (typeof checkpoint?.deltaToken != "string" ||
|
|
65
|
+
checkpoint.deltaToken.length == 0 ||
|
|
66
|
+
typeof checkpoint.lastPolledAt != "string" ||
|
|
67
|
+
Number.isNaN(Date.parse(checkpoint.lastPolledAt))) {
|
|
68
|
+
throw new PermanentPollError("OneDrive checkpoint is invalid; recreate the Trigger.");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
deltaToken: checkpoint.deltaToken,
|
|
72
|
+
lastPolledAt: checkpoint.lastPolledAt,
|
|
73
|
+
...(typeof checkpoint.pageToken == "string" && checkpoint.pageToken.length > 0
|
|
74
|
+
? { pageToken: checkpoint.pageToken }
|
|
75
|
+
: {}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function changedItems(context, checkpoint, pageSize) {
|
|
79
|
+
const items = new Map();
|
|
80
|
+
const result = await get(context, "/me/drive/root/delta", {
|
|
81
|
+
$top: Math.min(pageSize, maximumPollEventsPerPage),
|
|
82
|
+
token: checkpoint.pageToken ?? checkpoint.deltaToken,
|
|
83
|
+
});
|
|
84
|
+
deltaSuccess(result);
|
|
85
|
+
const parsed = (record(result.data) ?? {});
|
|
86
|
+
for (const item of parsed.value ?? [])
|
|
87
|
+
if (item.id != null && item.id.length > 0)
|
|
88
|
+
items.set(item.id, item);
|
|
89
|
+
if (parsed["@odata.deltaLink"]) {
|
|
90
|
+
return {
|
|
91
|
+
items,
|
|
92
|
+
next: {
|
|
93
|
+
checkpoint: {
|
|
94
|
+
deltaToken: requireToken(parsed["@odata.deltaLink"]),
|
|
95
|
+
lastPolledAt: context.now.toISOString(),
|
|
96
|
+
},
|
|
97
|
+
hasMore: false,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (!parsed["@odata.nextLink"])
|
|
102
|
+
throw new TransientPollError("OneDrive delta response has no continuation link.");
|
|
103
|
+
return {
|
|
104
|
+
items,
|
|
105
|
+
next: {
|
|
106
|
+
checkpoint: {
|
|
107
|
+
deltaToken: checkpoint.deltaToken,
|
|
108
|
+
lastPolledAt: checkpoint.lastPolledAt,
|
|
109
|
+
pageToken: requireToken(parsed["@odata.nextLink"]),
|
|
110
|
+
},
|
|
111
|
+
hasMore: true,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async function evaluate(id, item, config, checkpoint) {
|
|
116
|
+
if (item.root != null)
|
|
117
|
+
return "structural";
|
|
118
|
+
const itemType = type(item);
|
|
119
|
+
if (itemType == null)
|
|
120
|
+
return "structural";
|
|
121
|
+
const change = item.deleted != null
|
|
122
|
+
? "deleted"
|
|
123
|
+
: createdAfter(item.createdDateTime, new Date(checkpoint.lastPolledAt))
|
|
124
|
+
? "created"
|
|
125
|
+
: "updated";
|
|
126
|
+
if (!config.events.includes(change) || !config.itemTypes.includes(itemType))
|
|
127
|
+
return "filtered";
|
|
128
|
+
if (config.parentFolderId.length > 0 && item.parentReference?.id !== config.parentFolderId)
|
|
129
|
+
return "filtered";
|
|
130
|
+
if (config.itemId.length > 0 && id !== config.itemId)
|
|
131
|
+
return "filtered";
|
|
132
|
+
return await event(id, item, change, itemType, checkpoint.deltaToken);
|
|
133
|
+
}
|
|
134
|
+
function type(item) {
|
|
135
|
+
if (item.file != null)
|
|
136
|
+
return "file";
|
|
137
|
+
if (item.folder != null)
|
|
138
|
+
return "folder";
|
|
139
|
+
return item.deleted != null ? "file" : null;
|
|
140
|
+
}
|
|
141
|
+
async function event(id, item, change, itemType, deltaToken) {
|
|
142
|
+
// 同一轮分页共用删除事件标识,后续 delta 周期必须使用新标识。
|
|
143
|
+
return {
|
|
144
|
+
dedupeKey: item.deleted != null
|
|
145
|
+
? await digestBytes(canonicalJsonBytes(["one-drive-deleted", deltaToken, id]))
|
|
146
|
+
: `${id}:${item.eTag ?? item.lastModifiedDateTime}`,
|
|
147
|
+
payload: {
|
|
148
|
+
changeType: change,
|
|
149
|
+
createdDateTime: item.createdDateTime ?? item.fileSystemInfo?.createdDateTime ?? null,
|
|
150
|
+
driveId: item.parentReference?.driveId ?? null,
|
|
151
|
+
eTag: item.eTag ?? null,
|
|
152
|
+
itemId: id,
|
|
153
|
+
itemType,
|
|
154
|
+
lastModifiedDateTime: item.lastModifiedDateTime ?? item.fileSystemInfo?.lastModifiedDateTime ?? null,
|
|
155
|
+
mimeType: item.file?.mimeType ?? null,
|
|
156
|
+
name: item.name ?? "",
|
|
157
|
+
parentFolderId: item.parentReference?.id ?? null,
|
|
158
|
+
size: item.size ?? null,
|
|
159
|
+
webUrl: item.webUrl ?? "",
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async function get(context, endpoint, query) {
|
|
164
|
+
try {
|
|
165
|
+
return await context.connector.execute({ endpoint, method: "GET", query }, context.signal);
|
|
166
|
+
}
|
|
167
|
+
catch (cause) {
|
|
168
|
+
throw new TransientPollError(`OneDrive proxy request to ${endpoint} failed.`, { cause });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function deltaSuccess(result) {
|
|
172
|
+
if (result.status == 410)
|
|
173
|
+
throw new PermanentPollError("OneDrive delta token expired; recreate the Trigger.");
|
|
174
|
+
if (result.status == 404)
|
|
175
|
+
throw new PermanentPollError("OneDrive is not provisioned for this account.");
|
|
176
|
+
if (result.status == 400)
|
|
177
|
+
throw new PermanentPollError("OneDrive rejected the delta token; recreate the Trigger.");
|
|
178
|
+
success(result, "delta list");
|
|
179
|
+
}
|
|
180
|
+
function success(result, operation) {
|
|
181
|
+
if (result.status >= 200 && result.status < 300)
|
|
182
|
+
return;
|
|
183
|
+
if (result.status == 401 || result.status == 403)
|
|
184
|
+
throw new PollConnectionError(`OneDrive ${operation} rejected the Connection.`);
|
|
185
|
+
throw new TransientPollError(`OneDrive ${operation} failed with status ${result.status}.`);
|
|
186
|
+
}
|
|
187
|
+
function requireToken(link) {
|
|
188
|
+
const token = parseToken(link);
|
|
189
|
+
if (token == null)
|
|
190
|
+
throw new TransientPollError("OneDrive delta link has no token.");
|
|
191
|
+
return token;
|
|
192
|
+
}
|
|
193
|
+
function parseToken(link) {
|
|
194
|
+
const raw = /[?&]token=([^&#]+)/.exec(link)?.[1] ?? /\(token='([^']+)'\)/.exec(link)?.[1];
|
|
195
|
+
if (raw == null)
|
|
196
|
+
return null;
|
|
197
|
+
try {
|
|
198
|
+
return decodeURIComponent(raw);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return raw;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function createdAfter(value, boundary) {
|
|
205
|
+
if (value == null || value.length == 0)
|
|
206
|
+
return false;
|
|
207
|
+
const date = new Date(value);
|
|
208
|
+
return !Number.isNaN(date.getTime()) && date >= boundary;
|
|
209
|
+
}
|
|
210
|
+
function record(value) {
|
|
211
|
+
return value != null && typeof value == "object" && !Array.isArray(value)
|
|
212
|
+
? value
|
|
213
|
+
: undefined;
|
|
214
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
import type { IntegrationDefinition } from "../../triggers/common/integration.ts";
|
|
3
|
+
import type { PollDefinition } from "../../triggers/common/poll.ts";
|
|
2
4
|
export declare const proxy: ProviderProxyExecutor;
|
|
3
5
|
interface OutlookRequestInput {
|
|
4
6
|
accessToken: string;
|
|
@@ -13,4 +15,5 @@ interface OutlookRequestInput {
|
|
|
13
15
|
export declare const executors: ProviderExecutors;
|
|
14
16
|
export declare const credentialValidators: CredentialValidators;
|
|
15
17
|
export declare function outlookJsonRequest<T>(pathOrUrl: string, input: OutlookRequestInput): Promise<T>;
|
|
18
|
+
export declare const triggers: readonly (IntegrationDefinition | PollDefinition)[];
|
|
16
19
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { compactObject, requiredRecord } from "../../core/cast.js";
|
|
2
|
-
import { defineOAuthProviderExecutors, defineProviderProxy, ProviderRequestError } from "../provider-runtime.js";
|
|
2
|
+
import { defineOAuthProviderExecutors, defineProviderProxy, providerInputError, ProviderRequestError, } from "../provider-runtime.js";
|
|
3
3
|
import { microsoftGraphJson, microsoftGraphRequest } from "./microsoft-graph.js";
|
|
4
|
+
import { outlookMessageReceived } from "./trigger-on-message-received.js";
|
|
4
5
|
const outlookGraphBaseUrl = "https://graph.microsoft.com/v1.0";
|
|
5
6
|
export const proxy = defineProviderProxy({
|
|
6
7
|
service: "outlook",
|
|
@@ -93,6 +94,13 @@ function graphRequestOptions(input) {
|
|
|
93
94
|
function isAllowedOutlookMessageNextLinkPath(pathname) {
|
|
94
95
|
const normalizedPath = trimTrailingSlash(pathname);
|
|
95
96
|
const segments = normalizedPath.split("/").filter(Boolean);
|
|
97
|
+
// Delta continuation links (@odata.nextLink inside a delta round and
|
|
98
|
+
// @odata.deltaLink) end in a trailing `delta` segment on the two
|
|
99
|
+
// folder-scoped message-collection shapes. Graph tracks message changes per
|
|
100
|
+
// folder, so `/v1.0/me/messages/delta` is not admitted.
|
|
101
|
+
if (segments.length > 4 && segments[segments.length - 1] === "delta") {
|
|
102
|
+
segments.pop();
|
|
103
|
+
}
|
|
96
104
|
if (segments[0] !== "v1.0") {
|
|
97
105
|
return false;
|
|
98
106
|
}
|
|
@@ -162,12 +170,24 @@ async function listMailFolders(input, { accessToken, fetcher }) {
|
|
|
162
170
|
};
|
|
163
171
|
}
|
|
164
172
|
async function listMessages(input, { accessToken, fetcher }) {
|
|
165
|
-
|
|
173
|
+
// A nextLink continues the current page sequence; a deltaLink starts the
|
|
174
|
+
// next delta round. Both are opaque Graph URLs checked by the allowlist.
|
|
175
|
+
const followUpLink = typeof input.nextLink === "string"
|
|
166
176
|
? input.nextLink
|
|
167
|
-
: typeof input.
|
|
168
|
-
?
|
|
169
|
-
:
|
|
170
|
-
const
|
|
177
|
+
: typeof input.deltaLink === "string"
|
|
178
|
+
? input.deltaLink
|
|
179
|
+
: undefined;
|
|
180
|
+
const folderPath = typeof input.mailFolderId === "string"
|
|
181
|
+
? `me/mailFolders/${encodeURIComponent(input.mailFolderId)}/messages`
|
|
182
|
+
: undefined;
|
|
183
|
+
// Graph tracks message changes per folder: there is no mailbox-wide
|
|
184
|
+
// messages/delta, so a delta listing needs a folder.
|
|
185
|
+
if (followUpLink === undefined && input.delta === true && folderPath === undefined) {
|
|
186
|
+
throw providerInputError("mailFolderId is required when delta is true.");
|
|
187
|
+
}
|
|
188
|
+
const collectionPath = folderPath ?? "me/messages";
|
|
189
|
+
const pathOrUrl = followUpLink ?? (input.delta === true ? `${collectionPath}/delta` : collectionPath);
|
|
190
|
+
const query = followUpLink !== undefined
|
|
171
191
|
? undefined
|
|
172
192
|
: compactObject({
|
|
173
193
|
$top: typeof input.top === "number" ? String(input.top) : undefined,
|
|
@@ -186,9 +206,11 @@ async function listMessages(input, { accessToken, fetcher }) {
|
|
|
186
206
|
query,
|
|
187
207
|
headers,
|
|
188
208
|
});
|
|
209
|
+
// Rows stay raw: a delta round reports removals as `{ id, "@removed": {...} }`.
|
|
189
210
|
return {
|
|
190
211
|
messages: Array.isArray(payload.value) ? payload.value : [],
|
|
191
212
|
nextLink: typeof payload["@odata.nextLink"] === "string" ? payload["@odata.nextLink"] : null,
|
|
213
|
+
deltaLink: typeof payload["@odata.deltaLink"] === "string" ? payload["@odata.deltaLink"] : null,
|
|
192
214
|
};
|
|
193
215
|
}
|
|
194
216
|
async function getMessage(input, { accessToken, fetcher }) {
|
|
@@ -413,3 +435,4 @@ function requiredString(value, field) {
|
|
|
413
435
|
function asObject(value) {
|
|
414
436
|
return requiredRecord(value, "object input", (message) => new ProviderRequestError(400, message));
|
|
415
437
|
}
|
|
438
|
+
export const triggers = [outlookMessageReceived];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { optionalRecord, optionalString } from "../../core/cast.js";
|
|
2
|
-
import { ProviderRequestError, readProviderErrorTextBody, readProviderJsonBody, runProviderRequest, setSearchParams, } from "../provider-runtime.js";
|
|
2
|
+
import { ProviderRequestError, readProviderErrorTextBody, readProviderJsonBody, runProviderRequest, setSearchParams, withRetryAfterSeconds, } from "../provider-runtime.js";
|
|
3
3
|
const graphBaseUrl = "https://graph.microsoft.com/v1.0/";
|
|
4
4
|
const graphOrigin = "https://graph.microsoft.com";
|
|
5
5
|
/**
|
|
@@ -41,10 +41,13 @@ export async function microsoftGraphJson(pathOrUrl, options) {
|
|
|
41
41
|
}));
|
|
42
42
|
}
|
|
43
43
|
function buildMicrosoftGraphUrl(pathOrUrl, query, allowNextLink) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
// Code passes plain relative paths such as `me/messages`; anything else is a
|
|
45
|
+
// caller-supplied link that must pass the allowlist. A value with any scheme
|
|
46
|
+
// is parsed on its own: resolved against the base, `https:me/drive` would
|
|
47
|
+
// turn into a same-origin path that never reaches the allowlist.
|
|
48
|
+
const absolute = /^[a-z][a-z\d+.-]*:/i.test(pathOrUrl);
|
|
49
|
+
const requiresNextLinkValidation = absolute || !/^[a-z\d]/i.test(pathOrUrl);
|
|
50
|
+
const url = parseMicrosoftGraphUrl(pathOrUrl, absolute ? undefined : graphBaseUrl);
|
|
48
51
|
if (url.origin !== graphOrigin || url.protocol !== "https:") {
|
|
49
52
|
throw new ProviderRequestError(400, "Microsoft Graph URL must target https://graph.microsoft.com");
|
|
50
53
|
}
|
|
@@ -54,6 +57,14 @@ function buildMicrosoftGraphUrl(pathOrUrl, query, allowNextLink) {
|
|
|
54
57
|
setSearchParams(url, query ?? {});
|
|
55
58
|
return url;
|
|
56
59
|
}
|
|
60
|
+
function parseMicrosoftGraphUrl(pathOrUrl, base) {
|
|
61
|
+
try {
|
|
62
|
+
return new URL(pathOrUrl, base);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new ProviderRequestError(400, "Microsoft Graph URL must target https://graph.microsoft.com");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
57
68
|
async function microsoftGraphResponseError(response, options) {
|
|
58
69
|
const text = await readProviderErrorTextBody(response, `${options.label} error response`);
|
|
59
70
|
let code = "";
|
|
@@ -69,5 +80,5 @@ async function microsoftGraphResponseError(response, options) {
|
|
|
69
80
|
// Keep the upstream text when it is not JSON.
|
|
70
81
|
}
|
|
71
82
|
}
|
|
72
|
-
return new ProviderRequestError(response.status, options.refineErrorMessage?.(code, message) ?? message);
|
|
83
|
+
return new ProviderRequestError(response.status, options.refineErrorMessage?.(code, message) ?? message, withRetryAfterSeconds(response));
|
|
73
84
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsonSchema as s } from "../../core/json-schema.js";
|
|
2
|
+
const defaultFolder = "inbox";
|
|
3
|
+
const defaultPageSize = 25;
|
|
4
|
+
const eventSchema = s.object({
|
|
5
|
+
bodyPreview: s.string(),
|
|
6
|
+
categories: s.array(s.string()),
|
|
7
|
+
conversationId: s.string(),
|
|
8
|
+
from: s.string(),
|
|
9
|
+
fromName: s.string(),
|
|
10
|
+
hasAttachments: s.boolean(),
|
|
11
|
+
importance: s.string(),
|
|
12
|
+
internetMessageId: s.string(),
|
|
13
|
+
isDraft: s.boolean(),
|
|
14
|
+
isRead: s.boolean(),
|
|
15
|
+
messageId: s.string(),
|
|
16
|
+
parentFolderId: s.string(),
|
|
17
|
+
receivedDateTime: s.string(),
|
|
18
|
+
subject: s.string(),
|
|
19
|
+
to: s.array(s.string()),
|
|
20
|
+
webLink: s.string(),
|
|
21
|
+
}, {
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
required: [
|
|
24
|
+
"messageId",
|
|
25
|
+
"internetMessageId",
|
|
26
|
+
"conversationId",
|
|
27
|
+
"subject",
|
|
28
|
+
"bodyPreview",
|
|
29
|
+
"from",
|
|
30
|
+
"fromName",
|
|
31
|
+
"to",
|
|
32
|
+
"receivedDateTime",
|
|
33
|
+
"hasAttachments",
|
|
34
|
+
"isRead",
|
|
35
|
+
"isDraft",
|
|
36
|
+
"importance",
|
|
37
|
+
"categories",
|
|
38
|
+
"parentFolderId",
|
|
39
|
+
"webLink",
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
export const snapshot = {
|
|
43
|
+
configInputs: [
|
|
44
|
+
{
|
|
45
|
+
handle: "folder",
|
|
46
|
+
jsonSchema: s.string({ pattern: "^[A-Za-z0-9_=-]*$" }),
|
|
47
|
+
nullable: false,
|
|
48
|
+
value: defaultFolder,
|
|
49
|
+
description: "A well-known mail folder name, folder ID, or an empty string for the whole mailbox.",
|
|
50
|
+
},
|
|
51
|
+
{ handle: "includeDrafts", jsonSchema: s.boolean(), nullable: false, value: false },
|
|
52
|
+
{
|
|
53
|
+
handle: "maxMessagesPerPoll",
|
|
54
|
+
jsonSchema: s.integer({ maximum: 100, minimum: 1 }),
|
|
55
|
+
nullable: false,
|
|
56
|
+
value: defaultPageSize,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
handle: "readStatus",
|
|
60
|
+
jsonSchema: s.stringEnum(["All", "Read", "Unread"]),
|
|
61
|
+
nullable: false,
|
|
62
|
+
value: "All",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
handle: "senderAddress",
|
|
66
|
+
jsonSchema: s.string(),
|
|
67
|
+
nullable: false,
|
|
68
|
+
value: "",
|
|
69
|
+
description: "Exact sender address, or empty for any sender.",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
handle: "subjectContains",
|
|
73
|
+
jsonSchema: s.string(),
|
|
74
|
+
nullable: false,
|
|
75
|
+
value: "",
|
|
76
|
+
description: "Case-insensitive subject text.",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
handle: "withAttachmentsOnly",
|
|
80
|
+
jsonSchema: s.boolean(),
|
|
81
|
+
nullable: false,
|
|
82
|
+
value: false,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
definitionVersion: 2,
|
|
86
|
+
description: "Polls a Microsoft Outlook mail folder and triggers when a new message arrives.",
|
|
87
|
+
displayName: "New Message Received",
|
|
88
|
+
key: "outlook.on_message_received",
|
|
89
|
+
name: "on_message_received",
|
|
90
|
+
outputs: [{ handle: "events", jsonSchema: s.array(eventSchema), nullable: false }],
|
|
91
|
+
provider: "outlook",
|
|
92
|
+
type: "poll",
|
|
93
|
+
};
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { eventsPollOutputs, PermanentPollError, PollConnectionError, TransientPollError, } from "../../triggers/common/poll.js";
|
|
2
|
+
import { snapshot } from "./trigger-on-message-received.definition.js";
|
|
3
|
+
const markerPageSize = 100;
|
|
4
|
+
const seedAnchor = "1970-01-01T00:00:00Z";
|
|
5
|
+
const select = "id,internetMessageId,conversationId,subject,bodyPreview,from,toRecipients,receivedDateTime,hasAttachments,isRead,isDraft,importance,categories,parentFolderId,webLink";
|
|
6
|
+
export const outlookMessageReceived = {
|
|
7
|
+
buildOutputs: eventsPollOutputs,
|
|
8
|
+
snapshot,
|
|
9
|
+
async poll(context) {
|
|
10
|
+
const config = resolveConfig(context.config);
|
|
11
|
+
if (context.checkpoint === null)
|
|
12
|
+
return { checkpoint: (await seed(context, config)), events: [] };
|
|
13
|
+
const checkpoint = readCheckpoint(context.checkpoint);
|
|
14
|
+
const result = await get(context, endpoint(config.folder), {
|
|
15
|
+
$filter: filter(config, checkpoint.lastReceivedDateTime),
|
|
16
|
+
$orderby: "receivedDateTime asc",
|
|
17
|
+
$select: select,
|
|
18
|
+
$top: config.maxMessagesPerPoll,
|
|
19
|
+
});
|
|
20
|
+
success(result, "message list");
|
|
21
|
+
const rows = messages(result.data);
|
|
22
|
+
if (rows.length == 0)
|
|
23
|
+
return { checkpoint: checkpoint, events: [] };
|
|
24
|
+
const previousMs = Date.parse(checkpoint.lastReceivedDateTime);
|
|
25
|
+
let watermarkMs = previousMs;
|
|
26
|
+
let watermark = checkpoint.lastReceivedDateTime;
|
|
27
|
+
for (const row of rows) {
|
|
28
|
+
const ms = isoMs(row.receivedDateTime);
|
|
29
|
+
if (row.receivedDateTime != null && ms != null && ms > watermarkMs) {
|
|
30
|
+
watermarkMs = ms;
|
|
31
|
+
watermark = row.receivedDateTime;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const moved = watermarkMs > previousMs;
|
|
35
|
+
const processed = new Set(checkpoint.boundaryMessageIds);
|
|
36
|
+
const full = rows.length >= config.maxMessagesPerPoll;
|
|
37
|
+
if (full && !moved && rows.every((row) => typeof row.id == "string" && processed.has(row.id))) {
|
|
38
|
+
throw new PermanentPollError("Outlook cursor is stuck on a full timestamp boundary; increase maxMessagesPerPoll and resume the Trigger.");
|
|
39
|
+
}
|
|
40
|
+
const boundary = new Set(moved ? [] : checkpoint.boundaryMessageIds);
|
|
41
|
+
const events = [];
|
|
42
|
+
let filtered = 0;
|
|
43
|
+
for (const row of rows) {
|
|
44
|
+
if (row.id == null || row.id.length == 0)
|
|
45
|
+
continue;
|
|
46
|
+
if (isoMs(row.receivedDateTime) == watermarkMs)
|
|
47
|
+
boundary.add(row.id);
|
|
48
|
+
if (processed.has(row.id))
|
|
49
|
+
continue;
|
|
50
|
+
if (!matches(row, config)) {
|
|
51
|
+
filtered += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
events.push(event(row, row.id));
|
|
55
|
+
}
|
|
56
|
+
const hasMore = full && (moved || events.length > 0);
|
|
57
|
+
return {
|
|
58
|
+
checkpoint: { boundaryMessageIds: [...boundary], lastReceivedDateTime: watermark },
|
|
59
|
+
events,
|
|
60
|
+
filtered,
|
|
61
|
+
...(hasMore ? { hasMore: true } : {}),
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
function resolveConfig(value) {
|
|
66
|
+
return {
|
|
67
|
+
folder: value.folder,
|
|
68
|
+
includeDrafts: value.includeDrafts,
|
|
69
|
+
maxMessagesPerPoll: value.maxMessagesPerPoll,
|
|
70
|
+
readStatus: value.readStatus,
|
|
71
|
+
senderAddress: value.senderAddress.trim(),
|
|
72
|
+
subjectContains: value.subjectContains.trim(),
|
|
73
|
+
withAttachmentsOnly: value.withAttachmentsOnly,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function seed(context, config) {
|
|
77
|
+
const marker = await get(context, endpoint(config.folder), {
|
|
78
|
+
$orderby: "receivedDateTime desc",
|
|
79
|
+
$select: "id,receivedDateTime",
|
|
80
|
+
$top: markerPageSize,
|
|
81
|
+
});
|
|
82
|
+
success(marker, "seed marker fetch");
|
|
83
|
+
const shape = await get(context, endpoint(config.folder), {
|
|
84
|
+
$filter: filter(config, seedAnchor),
|
|
85
|
+
$orderby: "receivedDateTime desc",
|
|
86
|
+
$top: 1,
|
|
87
|
+
});
|
|
88
|
+
success(shape, "seed filter shape check");
|
|
89
|
+
const newest = newestMessage(messages(marker.data));
|
|
90
|
+
if (newest == null)
|
|
91
|
+
return { boundaryMessageIds: [], lastReceivedDateTime: context.now.toISOString() };
|
|
92
|
+
const boundary = messages(marker.data).filter((row) => isoMs(row.receivedDateTime) == newest.ms);
|
|
93
|
+
if (boundary.length >= config.maxMessagesPerPoll) {
|
|
94
|
+
return {
|
|
95
|
+
boundaryMessageIds: [],
|
|
96
|
+
lastReceivedDateTime: new Date(newest.ms + 1_000).toISOString(),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
boundaryMessageIds: boundary.flatMap((row) => (row.id == null || row.id.length == 0 ? [] : [row.id])),
|
|
101
|
+
lastReceivedDateTime: newest.iso,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function readCheckpoint(value) {
|
|
105
|
+
const checkpoint = record(value);
|
|
106
|
+
const watermark = checkpoint?.lastReceivedDateTime;
|
|
107
|
+
if (typeof watermark != "string" || isoMs(watermark) == null) {
|
|
108
|
+
throw new PermanentPollError("Outlook checkpoint is invalid; recreate the Trigger.");
|
|
109
|
+
}
|
|
110
|
+
const boundary = checkpoint?.boundaryMessageIds;
|
|
111
|
+
return {
|
|
112
|
+
boundaryMessageIds: Array.isArray(boundary)
|
|
113
|
+
? boundary.filter((id) => typeof id == "string" && id.length > 0)
|
|
114
|
+
: [],
|
|
115
|
+
lastReceivedDateTime: watermark,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function endpoint(folder) {
|
|
119
|
+
return folder.length == 0 ? "/me/messages" : `/me/mailFolders/${encodeURIComponent(folder)}/messages`;
|
|
120
|
+
}
|
|
121
|
+
function filter(config, watermark) {
|
|
122
|
+
const clauses = [`receivedDateTime ge ${watermark}`];
|
|
123
|
+
if (config.readStatus == "Unread")
|
|
124
|
+
clauses.push("isRead eq false");
|
|
125
|
+
if (config.readStatus == "Read")
|
|
126
|
+
clauses.push("isRead eq true");
|
|
127
|
+
if (config.withAttachmentsOnly)
|
|
128
|
+
clauses.push("hasAttachments eq true");
|
|
129
|
+
if (config.senderAddress.length > 0)
|
|
130
|
+
clauses.push(`from/emailAddress/address eq '${config.senderAddress.replaceAll("'", "''")}'`);
|
|
131
|
+
return clauses.join(" and ");
|
|
132
|
+
}
|
|
133
|
+
function matches(message, config) {
|
|
134
|
+
if (message.isDraft === true && !config.includeDrafts)
|
|
135
|
+
return false;
|
|
136
|
+
return (config.subjectContains.length == 0 ||
|
|
137
|
+
(message.subject ?? "").toLowerCase().includes(config.subjectContains.toLowerCase()));
|
|
138
|
+
}
|
|
139
|
+
function event(message, id) {
|
|
140
|
+
return {
|
|
141
|
+
dedupeKey: id,
|
|
142
|
+
payload: {
|
|
143
|
+
bodyPreview: message.bodyPreview ?? "",
|
|
144
|
+
categories: message.categories ?? [],
|
|
145
|
+
conversationId: message.conversationId ?? "",
|
|
146
|
+
from: message.from?.emailAddress?.address ?? "",
|
|
147
|
+
fromName: message.from?.emailAddress?.name ?? "",
|
|
148
|
+
hasAttachments: message.hasAttachments ?? false,
|
|
149
|
+
importance: message.importance ?? "",
|
|
150
|
+
internetMessageId: message.internetMessageId ?? "",
|
|
151
|
+
isDraft: message.isDraft ?? false,
|
|
152
|
+
isRead: message.isRead ?? false,
|
|
153
|
+
messageId: id,
|
|
154
|
+
parentFolderId: message.parentFolderId ?? "",
|
|
155
|
+
receivedDateTime: message.receivedDateTime ?? "",
|
|
156
|
+
subject: message.subject ?? "",
|
|
157
|
+
to: (message.toRecipients ?? []).flatMap(({ emailAddress }) => emailAddress?.address == null ? [] : [emailAddress.address]),
|
|
158
|
+
webLink: message.webLink ?? "",
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
async function get(context, path, query) {
|
|
163
|
+
try {
|
|
164
|
+
return await context.connector.execute({ endpoint: path, headers: { Prefer: 'IdType="ImmutableId"' }, method: "GET", query }, context.signal);
|
|
165
|
+
}
|
|
166
|
+
catch (cause) {
|
|
167
|
+
throw new TransientPollError(`Outlook proxy request to ${path} failed.`, { cause });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function success(result, operation) {
|
|
171
|
+
if (result.status >= 200 && result.status < 300)
|
|
172
|
+
return;
|
|
173
|
+
const codes = errorCodes(result.data);
|
|
174
|
+
if (result.status == 401)
|
|
175
|
+
throw new PollConnectionError(`Outlook ${operation} rejected the Connection.`);
|
|
176
|
+
if (result.status == 403 && codes.has("mailboxnotenabledforrestapi")) {
|
|
177
|
+
throw new PermanentPollError("The Outlook mailbox is not reachable through the Graph mail APIs.");
|
|
178
|
+
}
|
|
179
|
+
if (result.status == 403 && (codes.has("accessdenied") || codes.has("erroraccessdenied"))) {
|
|
180
|
+
throw new PollConnectionError(`Outlook ${operation} rejected the Connection.`);
|
|
181
|
+
}
|
|
182
|
+
if (result.status == 404 && (codes.has("erroritemnotfound") || codes.has("itemnotfound"))) {
|
|
183
|
+
throw new PermanentPollError("The configured Outlook folder does not exist.");
|
|
184
|
+
}
|
|
185
|
+
if (result.status == 400 && (codes.has("errorinvalididmalformed") || codes.has("inefficientfilter"))) {
|
|
186
|
+
throw new PermanentPollError("Outlook rejected the configured folder or filters.");
|
|
187
|
+
}
|
|
188
|
+
throw new TransientPollError(`Outlook ${operation} failed with status ${result.status}.`);
|
|
189
|
+
}
|
|
190
|
+
function errorCodes(data) {
|
|
191
|
+
const codes = new Set();
|
|
192
|
+
let value = record(data)?.error;
|
|
193
|
+
for (let depth = 0; depth < 4; depth += 1) {
|
|
194
|
+
const error = record(value);
|
|
195
|
+
if (error == null)
|
|
196
|
+
break;
|
|
197
|
+
if (typeof error.code == "string" && error.code.length > 0)
|
|
198
|
+
codes.add(error.code.toLowerCase());
|
|
199
|
+
value = error.innerError ?? error.innererror;
|
|
200
|
+
}
|
|
201
|
+
return codes;
|
|
202
|
+
}
|
|
203
|
+
function messages(data) {
|
|
204
|
+
const value = record(data)?.value;
|
|
205
|
+
return Array.isArray(value) ? value : [];
|
|
206
|
+
}
|
|
207
|
+
function newestMessage(rows) {
|
|
208
|
+
let newest = null;
|
|
209
|
+
for (const row of rows) {
|
|
210
|
+
const ms = isoMs(row.receivedDateTime);
|
|
211
|
+
if (row.receivedDateTime != null && ms != null && (newest == null || ms > newest.ms))
|
|
212
|
+
newest = { iso: row.receivedDateTime, ms };
|
|
213
|
+
}
|
|
214
|
+
return newest;
|
|
215
|
+
}
|
|
216
|
+
function isoMs(value) {
|
|
217
|
+
if (value == null || value.length == 0)
|
|
218
|
+
return null;
|
|
219
|
+
const milliseconds = Date.parse(value);
|
|
220
|
+
return Number.isNaN(milliseconds) ? null : milliseconds;
|
|
221
|
+
}
|
|
222
|
+
function record(value) {
|
|
223
|
+
return value != null && typeof value == "object" && !Array.isArray(value)
|
|
224
|
+
? value
|
|
225
|
+
: undefined;
|
|
226
|
+
}
|