@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,63 @@
|
|
|
1
|
+
import { jsonSchema as s } from "../../core/json-schema.js";
|
|
2
|
+
const idPattern = "^[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$";
|
|
3
|
+
const eventSchema = s.object({
|
|
4
|
+
createdBy: { type: "object" },
|
|
5
|
+
createdTime: s.string(),
|
|
6
|
+
dataSourceId: s.string(),
|
|
7
|
+
databaseId: s.string(),
|
|
8
|
+
event: s.stringEnum(["page_added", "page_updated"]),
|
|
9
|
+
lastEditedBy: { type: "object" },
|
|
10
|
+
lastEditedTime: s.string(),
|
|
11
|
+
pageId: s.string(),
|
|
12
|
+
properties: { type: "object" },
|
|
13
|
+
title: s.string(),
|
|
14
|
+
url: s.string(),
|
|
15
|
+
}, {
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
required: [
|
|
18
|
+
"event",
|
|
19
|
+
"pageId",
|
|
20
|
+
"databaseId",
|
|
21
|
+
"dataSourceId",
|
|
22
|
+
"url",
|
|
23
|
+
"title",
|
|
24
|
+
"createdTime",
|
|
25
|
+
"lastEditedTime",
|
|
26
|
+
"createdBy",
|
|
27
|
+
"lastEditedBy",
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
export const snapshot = {
|
|
31
|
+
configInputs: [
|
|
32
|
+
{
|
|
33
|
+
handle: "dataSourceId",
|
|
34
|
+
jsonSchema: s.string({
|
|
35
|
+
pattern: "^(?:|[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})$",
|
|
36
|
+
}),
|
|
37
|
+
nullable: false,
|
|
38
|
+
value: "",
|
|
39
|
+
},
|
|
40
|
+
{ handle: "databaseId", jsonSchema: s.string({ pattern: idPattern }), nullable: false },
|
|
41
|
+
{
|
|
42
|
+
handle: "events",
|
|
43
|
+
jsonSchema: s.array(s.stringEnum(["page_added", "page_updated"]), { minItems: 1, uniqueItems: true }),
|
|
44
|
+
nullable: false,
|
|
45
|
+
value: ["page_added"],
|
|
46
|
+
},
|
|
47
|
+
{ handle: "includeProperties", jsonSchema: s.boolean(), nullable: false, value: true },
|
|
48
|
+
{
|
|
49
|
+
handle: "maxItemsPerPoll",
|
|
50
|
+
jsonSchema: s.integer({ maximum: 100, minimum: 1 }),
|
|
51
|
+
nullable: false,
|
|
52
|
+
value: 25,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
definitionVersion: 2,
|
|
56
|
+
description: "Polls a Notion database and triggers when a page is added to it or an existing page is edited.",
|
|
57
|
+
displayName: "Database Page Added or Updated",
|
|
58
|
+
key: "notion.on_database_page_event",
|
|
59
|
+
name: "on_database_page_event",
|
|
60
|
+
outputs: [{ handle: "events", jsonSchema: s.array(eventSchema), nullable: false }],
|
|
61
|
+
provider: "notion",
|
|
62
|
+
type: "poll",
|
|
63
|
+
};
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { eventsPollOutputs, PermanentPollError, PollConnectionError, TransientPollError, } from "../../triggers/common/poll.js";
|
|
2
|
+
import { snapshot } from "./trigger-on-database-page-event.definition.js";
|
|
3
|
+
export const notionDatabasePageEvent = {
|
|
4
|
+
buildOutputs: eventsPollOutputs,
|
|
5
|
+
snapshot,
|
|
6
|
+
async poll(context) {
|
|
7
|
+
const config = resolveConfig(context.config);
|
|
8
|
+
if (context.checkpoint === null)
|
|
9
|
+
return seed(context, config);
|
|
10
|
+
const stored = readCheckpoint(context.checkpoint);
|
|
11
|
+
if (stored.target !== target(config))
|
|
12
|
+
return seed(context, config);
|
|
13
|
+
return drain(context, config, alignField(stored, cursorField(config.events)));
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
function resolveConfig(value) {
|
|
17
|
+
return {
|
|
18
|
+
dataSourceId: value.dataSourceId,
|
|
19
|
+
databaseId: value.databaseId,
|
|
20
|
+
events: [...new Set(value.events)],
|
|
21
|
+
includeProperties: value.includeProperties,
|
|
22
|
+
maxItemsPerPoll: value.maxItemsPerPoll,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function seed(context, config) {
|
|
26
|
+
const dataSourceId = await resolveDataSource(context, config);
|
|
27
|
+
const field = cursorField(config.events);
|
|
28
|
+
const result = await request(context, {
|
|
29
|
+
body: { page_size: 1, sorts: [{ direction: "ascending", timestamp: field }] },
|
|
30
|
+
endpoint: `/data_sources/${encodeURIComponent(dataSourceId)}/query`,
|
|
31
|
+
method: "POST",
|
|
32
|
+
});
|
|
33
|
+
success(result, "seed probe query");
|
|
34
|
+
return {
|
|
35
|
+
checkpoint: {
|
|
36
|
+
cursorField: field,
|
|
37
|
+
dataSourceId,
|
|
38
|
+
since: new Date(Math.ceil(context.now.getTime() / 60_000) * 60_000).toISOString(),
|
|
39
|
+
target: target(config),
|
|
40
|
+
},
|
|
41
|
+
events: [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function resolveDataSource(context, config) {
|
|
45
|
+
const result = await request(context, {
|
|
46
|
+
endpoint: `/databases/${encodeURIComponent(config.databaseId)}`,
|
|
47
|
+
method: "GET",
|
|
48
|
+
});
|
|
49
|
+
success(result, "database resolve");
|
|
50
|
+
const raw = record(result.data)?.data_sources;
|
|
51
|
+
const candidates = Array.isArray(raw)
|
|
52
|
+
? raw.flatMap((value) => {
|
|
53
|
+
const id = record(value)?.id;
|
|
54
|
+
return typeof id == "string" && id.length > 0 ? [id] : [];
|
|
55
|
+
})
|
|
56
|
+
: [];
|
|
57
|
+
if (config.dataSourceId.length > 0) {
|
|
58
|
+
const wanted = normalizeId(config.dataSourceId);
|
|
59
|
+
const match = candidates.find((id) => normalizeId(id) == wanted);
|
|
60
|
+
if (match == null)
|
|
61
|
+
throw new PermanentPollError("The Notion data source does not belong to the configured database.");
|
|
62
|
+
return match;
|
|
63
|
+
}
|
|
64
|
+
if (candidates.length == 1)
|
|
65
|
+
return candidates[0];
|
|
66
|
+
if (candidates.length == 0)
|
|
67
|
+
throw new PermanentPollError("The Notion database has no data sources.");
|
|
68
|
+
throw new PermanentPollError("The Notion database has multiple data sources; configure dataSourceId.");
|
|
69
|
+
}
|
|
70
|
+
function readCheckpoint(value) {
|
|
71
|
+
const checkpoint = record(value);
|
|
72
|
+
const field = checkpoint?.cursorField;
|
|
73
|
+
if (typeof checkpoint?.dataSourceId != "string" ||
|
|
74
|
+
checkpoint.dataSourceId.length == 0 ||
|
|
75
|
+
(field !== "created_time" && field !== "last_edited_time") ||
|
|
76
|
+
typeof checkpoint.since != "string" ||
|
|
77
|
+
checkpoint.since.length == 0) {
|
|
78
|
+
throw new PermanentPollError("Notion checkpoint is invalid; recreate the Trigger.");
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
cursorField: field,
|
|
82
|
+
dataSourceId: checkpoint.dataSourceId,
|
|
83
|
+
since: checkpoint.since,
|
|
84
|
+
target: typeof checkpoint.target == "string" ? checkpoint.target : "",
|
|
85
|
+
...(typeof checkpoint.startCursor == "string" && checkpoint.startCursor.length > 0
|
|
86
|
+
? { startCursor: checkpoint.startCursor }
|
|
87
|
+
: {}),
|
|
88
|
+
...(checkpoint.sinceExclusive === true ? { sinceExclusive: true } : {}),
|
|
89
|
+
...(checkpoint.sinceOnly === true ? { sinceOnly: true } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function cursorField(events) {
|
|
93
|
+
return events.length == 1 && events[0] == "page_added" ? "created_time" : "last_edited_time";
|
|
94
|
+
}
|
|
95
|
+
function alignField(checkpoint, field) {
|
|
96
|
+
return checkpoint.cursorField == field
|
|
97
|
+
? checkpoint
|
|
98
|
+
: {
|
|
99
|
+
cursorField: field,
|
|
100
|
+
dataSourceId: checkpoint.dataSourceId,
|
|
101
|
+
since: checkpoint.since,
|
|
102
|
+
target: checkpoint.target,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async function drain(context, config, checkpoint) {
|
|
106
|
+
const events = [];
|
|
107
|
+
let filtered = 0;
|
|
108
|
+
let consumed = 0;
|
|
109
|
+
let newest = null;
|
|
110
|
+
let startCursor = checkpoint.startCursor;
|
|
111
|
+
let ending = null;
|
|
112
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
113
|
+
const result = await request(context, {
|
|
114
|
+
body: queryBody(checkpoint, config.maxItemsPerPoll - consumed, startCursor),
|
|
115
|
+
endpoint: `/data_sources/${encodeURIComponent(checkpoint.dataSourceId)}/query`,
|
|
116
|
+
method: "POST",
|
|
117
|
+
});
|
|
118
|
+
if (result.status == 400 && startCursor != null) {
|
|
119
|
+
ending = "restarted";
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
success(result, "data source query");
|
|
123
|
+
const page = (record(result.data) ?? {});
|
|
124
|
+
for (const row of page.results ?? []) {
|
|
125
|
+
consumed += 1;
|
|
126
|
+
const timestamp = checkpoint.cursorField == "created_time" ? row.created_time : row.last_edited_time;
|
|
127
|
+
if (timestamp != null && timestamp.length > 0)
|
|
128
|
+
newest = later(newest, timestamp);
|
|
129
|
+
const kind = classify(row);
|
|
130
|
+
if (!config.events.includes(kind))
|
|
131
|
+
filtered += 1;
|
|
132
|
+
else
|
|
133
|
+
events.push(event(row, kind, config, checkpoint));
|
|
134
|
+
}
|
|
135
|
+
if (page.request_status?.type == "incomplete") {
|
|
136
|
+
ending = "truncated";
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
if (page.has_more !== true || typeof page.next_cursor != "string" || page.next_cursor.length == 0) {
|
|
140
|
+
ending = "complete";
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
startCursor = page.next_cursor;
|
|
144
|
+
if (consumed >= config.maxItemsPerPoll) {
|
|
145
|
+
ending = { nextCursor: page.next_cursor };
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (ending == null)
|
|
150
|
+
ending = { nextCursor: startCursor };
|
|
151
|
+
const base = {
|
|
152
|
+
cursorField: checkpoint.cursorField,
|
|
153
|
+
dataSourceId: checkpoint.dataSourceId,
|
|
154
|
+
target: checkpoint.target,
|
|
155
|
+
};
|
|
156
|
+
const next = typeof ending == "object"
|
|
157
|
+
? {
|
|
158
|
+
...base,
|
|
159
|
+
since: checkpoint.since,
|
|
160
|
+
startCursor: ending.nextCursor,
|
|
161
|
+
...modifiers(checkpoint),
|
|
162
|
+
}
|
|
163
|
+
: { ...base, ...advance(checkpoint, ending, newest, context.now) };
|
|
164
|
+
return {
|
|
165
|
+
checkpoint: next,
|
|
166
|
+
events,
|
|
167
|
+
filtered,
|
|
168
|
+
...(ending == "complete" ? {} : { hasMore: true }),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function advance(checkpoint, ending, newest, now) {
|
|
172
|
+
const pinned = { since: checkpoint.since, ...modifiers(checkpoint) };
|
|
173
|
+
const closed = Date.parse(checkpoint.since) + 60_000 <= now.getTime();
|
|
174
|
+
const escaped = closed ? { since: checkpoint.since, sinceExclusive: true } : pinned;
|
|
175
|
+
if (newest != null && after(newest, checkpoint.since))
|
|
176
|
+
return { since: newest };
|
|
177
|
+
if (ending == "restarted")
|
|
178
|
+
return pinned;
|
|
179
|
+
if (ending == "complete")
|
|
180
|
+
return checkpoint.sinceOnly === true || newest != null ? escaped : pinned;
|
|
181
|
+
if (newest == null)
|
|
182
|
+
return pinned;
|
|
183
|
+
return checkpoint.sinceOnly === true ? escaped : { since: checkpoint.since, sinceOnly: true };
|
|
184
|
+
}
|
|
185
|
+
function modifiers(checkpoint) {
|
|
186
|
+
return {
|
|
187
|
+
...(checkpoint.sinceExclusive === true ? { sinceExclusive: true } : {}),
|
|
188
|
+
...(checkpoint.sinceOnly === true ? { sinceOnly: true } : {}),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function queryBody(checkpoint, budget, startCursor) {
|
|
192
|
+
const field = checkpoint.cursorField;
|
|
193
|
+
const filter = checkpoint.sinceOnly === true
|
|
194
|
+
? {
|
|
195
|
+
and: [
|
|
196
|
+
{ [field]: { on_or_after: checkpoint.since }, timestamp: field },
|
|
197
|
+
{ [field]: { on_or_before: checkpoint.since }, timestamp: field },
|
|
198
|
+
],
|
|
199
|
+
}
|
|
200
|
+
: {
|
|
201
|
+
[field]: {
|
|
202
|
+
[checkpoint.sinceExclusive === true ? "after" : "on_or_after"]: checkpoint.since,
|
|
203
|
+
},
|
|
204
|
+
timestamp: field,
|
|
205
|
+
};
|
|
206
|
+
return {
|
|
207
|
+
filter,
|
|
208
|
+
page_size: Math.min(100, budget),
|
|
209
|
+
sorts: [{ direction: "ascending", timestamp: field }],
|
|
210
|
+
...(startCursor == null ? {} : { start_cursor: startCursor }),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function classify(page) {
|
|
214
|
+
return instant(page.created_time) === instant(page.last_edited_time) ? "page_added" : "page_updated";
|
|
215
|
+
}
|
|
216
|
+
function event(page, kind, config, checkpoint) {
|
|
217
|
+
return {
|
|
218
|
+
dedupeKey: kind == "page_added"
|
|
219
|
+
? `added:${page.id}`
|
|
220
|
+
: `updated:${page.id}:${instant(page.last_edited_time) ?? page.last_edited_time ?? ""}`,
|
|
221
|
+
payload: {
|
|
222
|
+
createdBy: { id: page.created_by?.id ?? "" },
|
|
223
|
+
createdTime: page.created_time ?? "",
|
|
224
|
+
dataSourceId: checkpoint.dataSourceId,
|
|
225
|
+
databaseId: canonicalId(config.databaseId),
|
|
226
|
+
event: kind,
|
|
227
|
+
lastEditedBy: { id: page.last_edited_by?.id ?? "" },
|
|
228
|
+
lastEditedTime: page.last_edited_time ?? "",
|
|
229
|
+
pageId: page.id,
|
|
230
|
+
...(config.includeProperties ? { properties: page.properties ?? {} } : {}),
|
|
231
|
+
title: title(page.properties ?? {}),
|
|
232
|
+
url: page.url ?? "",
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function title(properties) {
|
|
237
|
+
for (const value of Object.values(properties)) {
|
|
238
|
+
const property = record(value);
|
|
239
|
+
if (property?.type !== "title" || !Array.isArray(property.title))
|
|
240
|
+
continue;
|
|
241
|
+
return property.title
|
|
242
|
+
.map((part) => (typeof record(part)?.plain_text == "string" ? record(part).plain_text : ""))
|
|
243
|
+
.join("");
|
|
244
|
+
}
|
|
245
|
+
return "";
|
|
246
|
+
}
|
|
247
|
+
async function request(context, value) {
|
|
248
|
+
try {
|
|
249
|
+
return await context.connector.execute(value, context.signal);
|
|
250
|
+
}
|
|
251
|
+
catch (cause) {
|
|
252
|
+
throw new TransientPollError(`Notion proxy request to ${value.endpoint} failed.`, { cause });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function success(result, operation) {
|
|
256
|
+
if (result.status >= 200 && result.status < 300)
|
|
257
|
+
return;
|
|
258
|
+
if (result.status == 401 || result.status == 403)
|
|
259
|
+
throw new PollConnectionError(`Notion ${operation} rejected the Connection.`);
|
|
260
|
+
if (result.status == 404)
|
|
261
|
+
throw new PermanentPollError("The Notion target was not found or is not shared with the Connection.");
|
|
262
|
+
if (result.status == 400)
|
|
263
|
+
throw new PermanentPollError(`Notion ${operation} rejected the configuration.`);
|
|
264
|
+
throw new TransientPollError(`Notion ${operation} failed with status ${result.status}.`);
|
|
265
|
+
}
|
|
266
|
+
function target(config) {
|
|
267
|
+
return `${config.databaseId}|${config.dataSourceId}`;
|
|
268
|
+
}
|
|
269
|
+
function normalizeId(value) {
|
|
270
|
+
return value.replaceAll("-", "").toLowerCase();
|
|
271
|
+
}
|
|
272
|
+
function canonicalId(value) {
|
|
273
|
+
const hex = normalizeId(value);
|
|
274
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
275
|
+
}
|
|
276
|
+
function later(current, candidate) {
|
|
277
|
+
const timestamp = Date.parse(candidate);
|
|
278
|
+
return Number.isNaN(timestamp) || (current != null && timestamp < Date.parse(current)) ? current : candidate;
|
|
279
|
+
}
|
|
280
|
+
function after(left, right) {
|
|
281
|
+
return !Number.isNaN(Date.parse(left)) && !Number.isNaN(Date.parse(right)) && Date.parse(left) > Date.parse(right);
|
|
282
|
+
}
|
|
283
|
+
function instant(value) {
|
|
284
|
+
if (value == null || value.length == 0)
|
|
285
|
+
return null;
|
|
286
|
+
const milliseconds = Date.parse(value);
|
|
287
|
+
return Number.isNaN(milliseconds) ? null : new Date(milliseconds).toISOString();
|
|
288
|
+
}
|
|
289
|
+
function record(value) {
|
|
290
|
+
return value != null && typeof value == "object" && !Array.isArray(value)
|
|
291
|
+
? value
|
|
292
|
+
: undefined;
|
|
293
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { ProtocolError, SdkHttpError, UnauthorizedError } from "@modelcontextprotocol/client";
|
|
2
|
+
import { compactObject, looseArray, optionalBoolean, optionalInteger, optionalNumber, optionalRawString, optionalRecord, optionalString, optionalStringArray, requiredRawString, } from "../../core/cast.js";
|
|
3
|
+
import { withMcpClient } from "../mcp-client.js";
|
|
4
|
+
import { defineOAuthProviderExecutors, mapProviderActionSources, providerResponseError, providerUserAgent, ProviderRequestError, requiredInputString, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
|
|
5
|
+
import { notionMcpEndpoint } from "./endpoints.js";
|
|
6
|
+
import { decodeNotionToolText, parseNotionComments, parseNotionPage, parseNotionSearch, parseNotionSelf, parseNotionToolAccess, } from "./mcp-response.js";
|
|
7
|
+
const service = "notion_mcp";
|
|
8
|
+
const selfUserId = "self";
|
|
9
|
+
const toolsByAction = {
|
|
10
|
+
get_self: {
|
|
11
|
+
tool: "notion-get-users",
|
|
12
|
+
arguments: () => ({ user_id: selfUserId }),
|
|
13
|
+
parse: (value) => compactObject({ user: parseNotionSelf(value) }),
|
|
14
|
+
},
|
|
15
|
+
search: {
|
|
16
|
+
tool: "notion-search",
|
|
17
|
+
arguments: searchArguments,
|
|
18
|
+
parse: (value) => ({ ...parseNotionSearch(value) }),
|
|
19
|
+
},
|
|
20
|
+
fetch_page: {
|
|
21
|
+
tool: "notion-fetch",
|
|
22
|
+
arguments: (input) => ({ id: requiredInputString(input.id, "id") }),
|
|
23
|
+
parse: (value, input) => ({ id: requiredInputString(input.id, "id"), ...parseNotionPage(value) }),
|
|
24
|
+
},
|
|
25
|
+
list_comments: {
|
|
26
|
+
tool: "notion-get-comments",
|
|
27
|
+
arguments: (input) => ({
|
|
28
|
+
page_id: requiredInputString(input.page_id, "page_id"),
|
|
29
|
+
include_all_blocks: optionalBoolean(input.include_all_blocks) ?? true,
|
|
30
|
+
include_resolved: optionalBoolean(input.include_resolved) ?? true,
|
|
31
|
+
}),
|
|
32
|
+
parse: (value) => ({ comments: parseNotionComments(value) }),
|
|
33
|
+
},
|
|
34
|
+
tool_access: {
|
|
35
|
+
tool: "notion-get-tool-access",
|
|
36
|
+
arguments: () => ({}),
|
|
37
|
+
parse: (value) => ({ tools: parseNotionToolAccess(value) }),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const handlers = mapProviderActionSources(service, toolsByAction, (_actionName, source) => async (input, context) => {
|
|
41
|
+
const result = await callNotionTool(context, source.tool, source.arguments(input));
|
|
42
|
+
return { ...source.parse(result.value, input), raw: result.raw };
|
|
43
|
+
});
|
|
44
|
+
export const executors = defineOAuthProviderExecutors(service, handlers, {
|
|
45
|
+
skipDnsValidation: true,
|
|
46
|
+
});
|
|
47
|
+
export const credentialValidators = {
|
|
48
|
+
/** Require every tool the actions map, then identify the user so the account key is the Notion user ID. */
|
|
49
|
+
async oauth2(input, { fetcher, signal }) {
|
|
50
|
+
const context = { accessToken: input.accessToken, fetcher, signal };
|
|
51
|
+
const { toolCount, self } = await withNotionMcpClient(context, "validate", async (client, signal) => {
|
|
52
|
+
const tools = await listNotionTools(client, signal);
|
|
53
|
+
const available = new Set(tools.map((tool) => tool.name));
|
|
54
|
+
const missing = Object.values(toolsByAction)
|
|
55
|
+
.map((source) => source.tool)
|
|
56
|
+
.filter((tool) => !available.has(tool));
|
|
57
|
+
if (missing.length > 0) {
|
|
58
|
+
throw new ProviderRequestError(502, `Notion MCP did not expose the tools this connector needs: ${[...new Set(missing)].join(", ")}.`);
|
|
59
|
+
}
|
|
60
|
+
const result = await client.callTool({ name: toolsByAction.get_self.tool, arguments: toolsByAction.get_self.arguments({}) }, { signal });
|
|
61
|
+
return {
|
|
62
|
+
toolCount: tools.length,
|
|
63
|
+
self: parseNotionSelf(readNotionToolResult(toolsByAction.get_self.tool, result).value),
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
const accountId = self?.id;
|
|
67
|
+
if (!accountId)
|
|
68
|
+
throw providerResponseError("Notion MCP did not identify the connected user.");
|
|
69
|
+
return {
|
|
70
|
+
profile: { accountId, displayName: self.name ?? self.email ?? accountId },
|
|
71
|
+
grantedScopes: optionalString(input.metadata.scope)?.split(" ") ?? [],
|
|
72
|
+
metadata: { mcpEndpoint: notionMcpEndpoint, discoveredToolCount: toolCount },
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
/** The recorded notion-search arguments: typed filters nest under `filters`; extra ones pass through beneath them. */
|
|
77
|
+
function searchArguments(input) {
|
|
78
|
+
const filters = compactObject({
|
|
79
|
+
...optionalRecord(input.filters),
|
|
80
|
+
last_edited_date_range: optionalRecord(input.last_edited_date_range),
|
|
81
|
+
created_date_range: optionalRecord(input.created_date_range),
|
|
82
|
+
created_by_user_ids: optionalStringArray(input.created_by_user_ids),
|
|
83
|
+
edited_by_user_ids: optionalStringArray(input.edited_by_user_ids),
|
|
84
|
+
});
|
|
85
|
+
return compactObject({
|
|
86
|
+
query: optionalRawString(input.query) ?? "",
|
|
87
|
+
sort: optionalString(input.sort),
|
|
88
|
+
page_size: optionalInteger(input.page_size),
|
|
89
|
+
max_highlight_length: optionalInteger(input.max_highlight_length),
|
|
90
|
+
filters: Object.keys(filters).length > 0 ? filters : undefined,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async function listNotionTools(client, signal) {
|
|
94
|
+
const tools = [];
|
|
95
|
+
const cursors = new Set();
|
|
96
|
+
let cursor;
|
|
97
|
+
do {
|
|
98
|
+
const page = await client.listTools(cursor === undefined ? {} : { cursor }, { signal });
|
|
99
|
+
tools.push(...page.tools);
|
|
100
|
+
cursor = page.nextCursor;
|
|
101
|
+
if (cursor !== undefined) {
|
|
102
|
+
if (cursors.has(cursor))
|
|
103
|
+
throw providerResponseError("Notion MCP tools/list returned a repeated cursor.");
|
|
104
|
+
cursors.add(cursor);
|
|
105
|
+
}
|
|
106
|
+
} while (cursor !== undefined);
|
|
107
|
+
return tools;
|
|
108
|
+
}
|
|
109
|
+
async function callNotionTool(context, name, input) {
|
|
110
|
+
const result = await withNotionMcpClient(context, "execute", (client, signal) => client.callTool({ name, arguments: input }, { signal }));
|
|
111
|
+
return readNotionToolResult(name, result);
|
|
112
|
+
}
|
|
113
|
+
/** The text blocks joined are the raw answer; structured content, when the server sends it, is the value. */
|
|
114
|
+
function readNotionToolResult(name, result) {
|
|
115
|
+
const record = requiredResponseRecord(result, "Notion MCP result");
|
|
116
|
+
if (record.isError === true)
|
|
117
|
+
throw notionToolError(name, record);
|
|
118
|
+
const texts = looseArray(record.content).flatMap((block) => {
|
|
119
|
+
const item = optionalRecord(block);
|
|
120
|
+
return item?.type === "text" ? [requiredRawString(item.text, "Notion MCP text", providerResponseError)] : [];
|
|
121
|
+
});
|
|
122
|
+
const structured = optionalRecord(record.structuredContent);
|
|
123
|
+
if (texts.length === 0 && structured === undefined)
|
|
124
|
+
throw providerResponseError("Notion MCP returned no content.");
|
|
125
|
+
const raw = texts.length > 0 ? texts.join("\n") : JSON.stringify(structured);
|
|
126
|
+
return { raw, value: structured ?? decodeNotionToolText(raw) };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A tool error. Notion returns a rate limit it does not wait out as a tool error whose `structuredContent.error`
|
|
130
|
+
* carries `code: "rate_limited"` and, when known, `retry_after_seconds`; that one is a 429, the rest a 502.
|
|
131
|
+
*/
|
|
132
|
+
function notionToolError(name, record) {
|
|
133
|
+
const error = optionalRecord(optionalRecord(record.structuredContent)?.error);
|
|
134
|
+
if (error?.code === "rate_limited") {
|
|
135
|
+
const retryAfter = optionalNumber(error.retry_after_seconds);
|
|
136
|
+
const wait = retryAfter === undefined ? "" : `; retry after ${retryAfter} seconds`;
|
|
137
|
+
return new ProviderRequestError(429, `Notion MCP tool ${name} was rate limited${wait}.`, record);
|
|
138
|
+
}
|
|
139
|
+
return new ProviderRequestError(502, `Notion MCP tool ${name} failed.`, record);
|
|
140
|
+
}
|
|
141
|
+
function withNotionMcpClient(context, phase, run) {
|
|
142
|
+
return runProviderRequest({ signal: context.signal, label: "Notion MCP" }, (signal) => withMcpClient({
|
|
143
|
+
endpoint: new URL(notionMcpEndpoint),
|
|
144
|
+
transport: "streamable_http",
|
|
145
|
+
fetcher: context.fetcher,
|
|
146
|
+
headers: { authorization: `Bearer ${context.accessToken}`, "user-agent": providerUserAgent },
|
|
147
|
+
redirect: "manual",
|
|
148
|
+
signal,
|
|
149
|
+
mapError: (error) => mapNotionMcpError(error, phase),
|
|
150
|
+
}, (client) => run(client, signal)));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Sign-in reports a rejected token as invalid input (400); a run reports it as an expired authorization (401).
|
|
154
|
+
* Anything unrecognized is left to runProviderRequest, which tells a timeout (504) from a failure (502).
|
|
155
|
+
*/
|
|
156
|
+
function mapNotionMcpError(error, phase) {
|
|
157
|
+
if (error instanceof ProviderRequestError)
|
|
158
|
+
return error;
|
|
159
|
+
const credentialStatus = phase === "validate" ? 400 : 401;
|
|
160
|
+
if (error instanceof UnauthorizedError) {
|
|
161
|
+
return new ProviderRequestError(credentialStatus, "Notion MCP credential is invalid or expired.");
|
|
162
|
+
}
|
|
163
|
+
if (error instanceof SdkHttpError) {
|
|
164
|
+
const status = error.status;
|
|
165
|
+
if (status === 401 || status === 403) {
|
|
166
|
+
return new ProviderRequestError(credentialStatus, "Notion MCP credential is invalid or expired.");
|
|
167
|
+
}
|
|
168
|
+
// The SDK error carries the response body; only the status is reported so a token echoed in it never is.
|
|
169
|
+
const providerStatus = 400 <= status && status < 500 ? status : 502;
|
|
170
|
+
return new ProviderRequestError(providerStatus, `Notion MCP request failed with HTTP ${status}.`);
|
|
171
|
+
}
|
|
172
|
+
if (error instanceof ProtocolError) {
|
|
173
|
+
return new ProviderRequestError(502, `Notion MCP request failed: ${error.message}`);
|
|
174
|
+
}
|
|
175
|
+
return error;
|
|
176
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Readers for the text envelopes Notion's beta MCP tools answer in, as they were recorded live. Every reader is
|
|
3
|
+
* defensive: a field the server omits is absent from the typed result, an unrecognized shape yields an empty
|
|
4
|
+
* result, and nothing here throws, because the caller keeps the raw text beside the typed fields.
|
|
5
|
+
*/
|
|
6
|
+
interface NotionMcpUser {
|
|
7
|
+
id?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
email?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
}
|
|
12
|
+
interface NotionMcpSearchResult {
|
|
13
|
+
id?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
timestamp?: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
}
|
|
20
|
+
interface NotionMcpSearch {
|
|
21
|
+
type: string | undefined;
|
|
22
|
+
results: NotionMcpSearchResult[];
|
|
23
|
+
notices: string[];
|
|
24
|
+
}
|
|
25
|
+
interface NotionMcpPage {
|
|
26
|
+
title?: string;
|
|
27
|
+
url?: string;
|
|
28
|
+
page_last_edited_at?: string;
|
|
29
|
+
properties?: string;
|
|
30
|
+
content?: string;
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface NotionMcpComment {
|
|
34
|
+
id?: string;
|
|
35
|
+
discussion_id?: string;
|
|
36
|
+
plain_text?: string;
|
|
37
|
+
created_time?: string;
|
|
38
|
+
created_by?: NotionMcpUser;
|
|
39
|
+
}
|
|
40
|
+
interface NotionMcpToolRestriction {
|
|
41
|
+
parameter: string;
|
|
42
|
+
reason: string;
|
|
43
|
+
}
|
|
44
|
+
interface NotionMcpToolAccess {
|
|
45
|
+
tool: string;
|
|
46
|
+
status: string | undefined;
|
|
47
|
+
restricted_parameters: NotionMcpToolRestriction[];
|
|
48
|
+
upgrade_url: string | undefined;
|
|
49
|
+
full_version_url: string | undefined;
|
|
50
|
+
landing_page_url: string | undefined;
|
|
51
|
+
landing_page_action: string | undefined;
|
|
52
|
+
}
|
|
53
|
+
/** Notion's tools answer JSON in a text block on most calls and prose or XML fragments on the rest. */
|
|
54
|
+
export declare function decodeNotionToolText(text: string): unknown;
|
|
55
|
+
/**
|
|
56
|
+
* The connected user as notion-get-users answers `user_id: "self"`: the first listed user of
|
|
57
|
+
* `{results: [{type, id, name, email}], has_more}` that carries an ID or an email, or the answer itself when it is a
|
|
58
|
+
* single user.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseNotionSelf(value: unknown): NotionMcpUser | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Search results plus the server's notices, such as a filter dropped on the connected plan, and the search `type`
|
|
63
|
+
* the server reports: `workspace_search`, or `ai_search` when it routed a keyword query to Notion AI search.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseNotionSearch(value: unknown): NotionMcpSearch;
|
|
66
|
+
/**
|
|
67
|
+
* The page envelope notion-fetch answers: a preamble line, then
|
|
68
|
+
* `<page url="..."><properties>...</properties><content>MARKDOWN</content></page>`, either bare in the text block or
|
|
69
|
+
* under `text` of a `{title, url, page_last_edited_at, text}` object. A page the server cut says so with a
|
|
70
|
+
* `truncated` flag on the object or on the tag.
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseNotionPage(value: unknown): NotionMcpPage;
|
|
73
|
+
/**
|
|
74
|
+
* Comments as notion-get-comments answers them, in both recorded shapes: the structured
|
|
75
|
+
* `{discussions: [{id, comments: [{id, plain_text, created_time, created_by}]}]}` (or a flat `{comments: [...]}`),
|
|
76
|
+
* or the XML twin `<discussion id><comment id author author_id created_time>text</comment></discussion>`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function parseNotionComments(value: unknown): NotionMcpComment[];
|
|
79
|
+
/**
|
|
80
|
+
* The plan report notion-get-tool-access answers: `{current_tool_access: {<tool>: {status, restricted_parameters?,
|
|
81
|
+
* upgrade_url?, full_version_url?, landing_page_url?, landing_page_action?}}}`, keyed by each tool's base name
|
|
82
|
+
* (`search`, `ai_search`), where `restricted_parameters` maps a parameter path such as `filters.title_only` to the
|
|
83
|
+
* reason it is unavailable. The reason is kept as text and never interpreted.
|
|
84
|
+
*/
|
|
85
|
+
export declare function parseNotionToolAccess(value: unknown): NotionMcpToolAccess[];
|
|
86
|
+
export {};
|