@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
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { Pool } from "pg";
|
|
2
|
-
import { parseRuntimeActionHttpResult } from "
|
|
3
|
-
import { PlainTextSecretCodec } from "
|
|
4
|
-
import { ConnectionRequestStore } from "
|
|
5
|
-
import {
|
|
6
|
-
import { listRunLogs, parseJson, readRunLogRow, readRuntimePolicyRow, readRuntimeTokenRow, readString, runtimeTokenColumns, } from "
|
|
7
|
-
import { DEFAULT_RUN_LIMIT } from "
|
|
2
|
+
import { parseRuntimeActionHttpResult } from "../../api/runtime-api.js";
|
|
3
|
+
import { PlainTextSecretCodec } from "../../secrets/secret-codec-core.js";
|
|
4
|
+
import { ConnectionRequestStore } from "../connection-request-store.js";
|
|
5
|
+
import { SqlConnectionStore } from "../connection-store.js";
|
|
6
|
+
import { listRunLogs, parseJson, readRunLogRow, readRuntimePolicyRow, readRuntimeTokenRow, readString, runtimeTokenColumns, } from "../runtime-sql.js";
|
|
7
|
+
import { DEFAULT_RUN_LIMIT } from "../runtime-store.js";
|
|
8
|
+
import { SaasProjectStore } from "../saas-project-store.js";
|
|
9
|
+
import { SqlTriggerStore } from "../trigger-store.js";
|
|
10
|
+
import { assertPostgresSchemaReady } from "./migrations.js";
|
|
8
11
|
export class PostgresRuntimeDatabase {
|
|
12
|
+
saasProjectStore;
|
|
9
13
|
connectionRequestStore;
|
|
10
14
|
connectionStore;
|
|
15
|
+
triggerStore;
|
|
11
16
|
oauthClientConfigStore;
|
|
12
17
|
oauthStateStore;
|
|
13
18
|
runtimeTokenStore;
|
|
@@ -20,7 +25,7 @@ export class PostgresRuntimeDatabase {
|
|
|
20
25
|
constructor(pool, options) {
|
|
21
26
|
this.pool = pool;
|
|
22
27
|
this.secretCodec = options.secretCodec ?? new PlainTextSecretCodec();
|
|
23
|
-
|
|
28
|
+
const transaction = (statements) => runInTransaction(pool, async (client) => {
|
|
24
29
|
// Serialize request transitions across processes, including first requests with no row to lock.
|
|
25
30
|
await client.query("select pg_advisory_xact_lock(1326382671, 2)");
|
|
26
31
|
const results = [];
|
|
@@ -29,8 +34,11 @@ export class PostgresRuntimeDatabase {
|
|
|
29
34
|
results.push((await client.query(sql.replaceAll("?", () => `$${++index}`), values)).rows);
|
|
30
35
|
}
|
|
31
36
|
return results;
|
|
32
|
-
})
|
|
33
|
-
this.
|
|
37
|
+
});
|
|
38
|
+
this.connectionRequestStore = new ConnectionRequestStore(transaction, this.secretCodec);
|
|
39
|
+
this.connectionStore = new SqlConnectionStore(transaction, this.secretCodec);
|
|
40
|
+
this.triggerStore = new SqlTriggerStore(transaction, this.secretCodec);
|
|
41
|
+
this.saasProjectStore = new SaasProjectStore(transaction, this.secretCodec);
|
|
34
42
|
this.oauthClientConfigStore = new PostgresOAuthClientConfigStore(pool, this.secretCodec);
|
|
35
43
|
this.oauthStateStore = new PostgresOAuthStateStore(pool, this.secretCodec);
|
|
36
44
|
this.runtimeTokenStore = new PostgresRuntimeTokenStore(pool);
|
|
@@ -63,8 +71,13 @@ export class PostgresRuntimeDatabase {
|
|
|
63
71
|
}
|
|
64
72
|
async resetRuntimeData() {
|
|
65
73
|
await runInTransaction(this.pool, async (client) => {
|
|
74
|
+
await client.query("select pg_advisory_xact_lock(1326382671, 2)");
|
|
66
75
|
await client.query(`
|
|
67
|
-
delete from
|
|
76
|
+
delete from oauth_sources;
|
|
77
|
+
delete from saas_cleanup;
|
|
78
|
+
delete from managed_project;
|
|
79
|
+
delete from trigger_subscriptions;
|
|
80
|
+
delete from connections;
|
|
68
81
|
delete from oauth_client_configs;
|
|
69
82
|
delete from oauth_states;
|
|
70
83
|
delete from connection_requests;
|
|
@@ -79,7 +92,37 @@ export class PostgresRuntimeDatabase {
|
|
|
79
92
|
}
|
|
80
93
|
async rotateSecretCodec(nextSecretCodec) {
|
|
81
94
|
await runInTransaction(this.pool, async (client) => {
|
|
82
|
-
await client.query("
|
|
95
|
+
await client.query("select pg_advisory_xact_lock(1326382671, 2)");
|
|
96
|
+
await client.query("lock table connections, oauth_client_configs, oauth_states, connection_requests, idempotency_records, managed_project, oauth_sources, saas_cleanup, instance_identity, trigger_subscriptions in access exclusive mode");
|
|
97
|
+
const project = await client.query("select value from managed_project where id = 1");
|
|
98
|
+
if (project.rows.length && !nextSecretCodec.encrypted)
|
|
99
|
+
throw new Error("SaaS project configuration requires encrypted storage.");
|
|
100
|
+
for (const row of project.rows) {
|
|
101
|
+
const value = await nextSecretCodec.encode(await this.secretCodec.decode(readString(row, "value")));
|
|
102
|
+
await client.query("update managed_project set value = $1 where id = 1", [value]);
|
|
103
|
+
}
|
|
104
|
+
const candidates = await client.query("select id, candidate_value from connection_requests where candidate_value is not null");
|
|
105
|
+
for (const row of candidates.rows) {
|
|
106
|
+
const value = await nextSecretCodec.encode(await this.secretCodec.decode(readString(row, "candidate_value")));
|
|
107
|
+
await client.query("update connection_requests set candidate_value = $1 where id = $2", [
|
|
108
|
+
value,
|
|
109
|
+
readString(row, "id"),
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
const returnUris = await client.query("select id, return_uri from connection_requests where return_uri is not null");
|
|
113
|
+
for (const row of returnUris.rows) {
|
|
114
|
+
const value = await nextSecretCodec.encode(await this.secretCodec.decode(readString(row, "return_uri")));
|
|
115
|
+
await client.query("update connection_requests set return_uri = $1 where id = $2", [
|
|
116
|
+
value,
|
|
117
|
+
readString(row, "id"),
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
const triggerRows = await client.query("select id, value from trigger_subscriptions");
|
|
121
|
+
for (const row of triggerRows.rows)
|
|
122
|
+
await client.query("update trigger_subscriptions set value = $1 where id = $2", [
|
|
123
|
+
await nextSecretCodec.encode(await this.secretCodec.decode(readString(row, "value"))),
|
|
124
|
+
readString(row, "id"),
|
|
125
|
+
]);
|
|
83
126
|
const connectionRows = await client.query("select service, connection_name, value from connections");
|
|
84
127
|
const connections = await Promise.all(connectionRows.rows.map(async (row) => ({
|
|
85
128
|
service: readString(row, "service"),
|
|
@@ -167,86 +210,6 @@ class PostgresMarketplaceStore {
|
|
|
167
210
|
await this.pool.query("insert into provider_preferences (service, enabled, created_at, updated_at) values ($1, $2, $3, $4) on conflict(service) do update set enabled = excluded.enabled, updated_at = excluded.updated_at", [preference.service, preference.enabled, preference.createdAt, preference.updatedAt]);
|
|
168
211
|
}
|
|
169
212
|
}
|
|
170
|
-
class PostgresConnectionStore {
|
|
171
|
-
pool;
|
|
172
|
-
secretCodec;
|
|
173
|
-
constructor(pool, secretCodec) {
|
|
174
|
-
this.pool = pool;
|
|
175
|
-
this.secretCodec = secretCodec;
|
|
176
|
-
}
|
|
177
|
-
async get(service, connectionName) {
|
|
178
|
-
const result = await this.pool.query("select id, revision, value from connections where service = $1 and connection_name = $2", [service, connectionName]);
|
|
179
|
-
const row = result.rows[0];
|
|
180
|
-
return row
|
|
181
|
-
? {
|
|
182
|
-
id: readString(row, "id"),
|
|
183
|
-
revision: readString(row, "revision"),
|
|
184
|
-
service,
|
|
185
|
-
connectionName,
|
|
186
|
-
credential: parseJson(await this.secretCodec.decode(readString(row, "value"))),
|
|
187
|
-
}
|
|
188
|
-
: undefined;
|
|
189
|
-
}
|
|
190
|
-
async set(service, connectionName, credential) {
|
|
191
|
-
const result = await this.pool.query(`
|
|
192
|
-
insert into connections (id, revision, service, connection_name, value, updated_at)
|
|
193
|
-
values ($1, $2, $3, $4, $5, $6)
|
|
194
|
-
on conflict(service, connection_name) do update set
|
|
195
|
-
revision = excluded.revision,
|
|
196
|
-
value = excluded.value,
|
|
197
|
-
updated_at = excluded.updated_at
|
|
198
|
-
returning id, revision
|
|
199
|
-
`, [
|
|
200
|
-
crypto.randomUUID(),
|
|
201
|
-
crypto.randomUUID(),
|
|
202
|
-
service,
|
|
203
|
-
connectionName,
|
|
204
|
-
await this.secretCodec.encode(JSON.stringify(credential)),
|
|
205
|
-
new Date().toISOString(),
|
|
206
|
-
]);
|
|
207
|
-
const row = result.rows[0];
|
|
208
|
-
return {
|
|
209
|
-
id: readString(row, "id"),
|
|
210
|
-
revision: readString(row, "revision"),
|
|
211
|
-
service,
|
|
212
|
-
connectionName,
|
|
213
|
-
credential,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
async updateCredential(input) {
|
|
217
|
-
const result = await this.pool.query(`
|
|
218
|
-
update connections
|
|
219
|
-
set revision = $1, value = $2, updated_at = $3
|
|
220
|
-
where service = $4 and connection_name = $5 and id = $6 and revision = $7
|
|
221
|
-
returning id
|
|
222
|
-
`, [
|
|
223
|
-
crypto.randomUUID(),
|
|
224
|
-
await this.secretCodec.encode(JSON.stringify(input.credential)),
|
|
225
|
-
new Date().toISOString(),
|
|
226
|
-
input.service,
|
|
227
|
-
input.connectionName,
|
|
228
|
-
input.id,
|
|
229
|
-
input.revision,
|
|
230
|
-
]);
|
|
231
|
-
return (result.rowCount ?? 0) > 0;
|
|
232
|
-
}
|
|
233
|
-
async delete(service, connectionName) {
|
|
234
|
-
await this.pool.query("delete from connections where service = $1 and connection_name = $2", [
|
|
235
|
-
service,
|
|
236
|
-
connectionName,
|
|
237
|
-
]);
|
|
238
|
-
}
|
|
239
|
-
async list() {
|
|
240
|
-
const result = await this.pool.query("select id, revision, service, connection_name, value from connections order by service, connection_name");
|
|
241
|
-
return await Promise.all(result.rows.map(async (row) => ({
|
|
242
|
-
id: readString(row, "id"),
|
|
243
|
-
revision: readString(row, "revision"),
|
|
244
|
-
service: readString(row, "service"),
|
|
245
|
-
connectionName: readString(row, "connection_name"),
|
|
246
|
-
credential: parseJson(await this.secretCodec.decode(readString(row, "value"))),
|
|
247
|
-
})));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
213
|
class PostgresOAuthClientConfigStore {
|
|
251
214
|
pool;
|
|
252
215
|
secretCodec;
|
|
@@ -313,7 +276,7 @@ class PostgresRuntimeTokenStore {
|
|
|
313
276
|
insert into runtime_tokens (
|
|
314
277
|
${runtimeTokenColumns}
|
|
315
278
|
)
|
|
316
|
-
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
279
|
+
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
317
280
|
`, [
|
|
318
281
|
record.id,
|
|
319
282
|
record.name,
|
|
@@ -322,6 +285,7 @@ class PostgresRuntimeTokenStore {
|
|
|
322
285
|
JSON.stringify(record.blockedActions),
|
|
323
286
|
JSON.stringify(record.allowedProxies),
|
|
324
287
|
JSON.stringify(record.allowedConnections ?? []),
|
|
288
|
+
JSON.stringify(record.allowedTriggers ?? []),
|
|
325
289
|
record.createdAt,
|
|
326
290
|
record.lastUsedAt ?? null,
|
|
327
291
|
]);
|
|
@@ -346,14 +310,15 @@ class PostgresRuntimeTokenStore {
|
|
|
346
310
|
async updatePolicy(id, policy) {
|
|
347
311
|
const result = await this.pool.query(`
|
|
348
312
|
update runtime_tokens
|
|
349
|
-
set allowed_actions = $1, blocked_actions = $2, allowed_proxies = $3, allowed_connections = $4
|
|
350
|
-
where id = $
|
|
313
|
+
set allowed_actions = $1, blocked_actions = $2, allowed_proxies = $3, allowed_connections = $4, allowed_triggers = $5
|
|
314
|
+
where id = $6
|
|
351
315
|
returning ${runtimeTokenColumns}
|
|
352
316
|
`, [
|
|
353
317
|
JSON.stringify(policy.allowedActions),
|
|
354
318
|
JSON.stringify(policy.blockedActions),
|
|
355
319
|
JSON.stringify(policy.allowedProxies),
|
|
356
320
|
JSON.stringify(policy.allowedConnections ?? []),
|
|
321
|
+
JSON.stringify(policy.allowedTriggers ?? []),
|
|
357
322
|
id,
|
|
358
323
|
]);
|
|
359
324
|
const row = result.rows[0];
|
|
@@ -2,14 +2,18 @@ import type { IConnectionStore } from "../../connection-service.ts";
|
|
|
2
2
|
import type { IMarketplaceStore } from "../../marketplace/marketplace-service.ts";
|
|
3
3
|
import type { IOAuthClientConfigStore } from "../../oauth/oauth-client-config-service.ts";
|
|
4
4
|
import type { IOAuthStateStore } from "../../oauth/oauth-flow-service.ts";
|
|
5
|
+
import type { TriggerStore } from "../../triggers/store.ts";
|
|
5
6
|
import type { ConnectionRequestStore } from "./connection-request-store.ts";
|
|
6
7
|
import type { IIdempotencyStore } from "./idempotency-store.ts";
|
|
7
8
|
import type { IRuntimePolicyStore } from "./runtime-policy-store.ts";
|
|
8
9
|
import type { IRunLogStore } from "./runtime-store.ts";
|
|
9
10
|
import type { IRuntimeTokenStore } from "./runtime-token-service.ts";
|
|
11
|
+
import type { SaasProjectStore } from "./saas-project-store.ts";
|
|
10
12
|
export interface RuntimeDatabase {
|
|
13
|
+
saasProjectStore: SaasProjectStore;
|
|
11
14
|
connectionRequestStore: ConnectionRequestStore;
|
|
12
15
|
connectionStore: IConnectionStore;
|
|
16
|
+
triggerStore: TriggerStore;
|
|
13
17
|
oauthClientConfigStore: IOAuthClientConfigStore;
|
|
14
18
|
oauthStateStore: IOAuthStateStore;
|
|
15
19
|
runtimeTokenStore: IRuntimeTokenStore;
|
|
@@ -7,7 +7,7 @@ import type { RuntimeTokenRecord } from "./runtime-token-service.ts";
|
|
|
7
7
|
/** One row a runtime store backend read back from its database driver. */
|
|
8
8
|
export type RuntimeRow = Record<string, unknown>;
|
|
9
9
|
/** The `runtime_tokens` columns every token query reads back, in the order `readRuntimeTokenRow` decodes. */
|
|
10
|
-
export declare const runtimeTokenColumns = "id, name, token_hash, allowed_actions, blocked_actions, allowed_proxies, allowed_connections, created_at, last_used_at";
|
|
10
|
+
export declare const runtimeTokenColumns = "id, name, token_hash, allowed_actions, blocked_actions, allowed_proxies, allowed_connections, allowed_triggers, created_at, last_used_at";
|
|
11
11
|
/** Read a column the query selected as a string, rejecting anything the schema cannot produce. */
|
|
12
12
|
export declare function readString(row: RuntimeRow, key: string): string;
|
|
13
13
|
/** Parse a JSON column, trusting the shape the store wrote. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decodeRunLogCursor, encodeRunLogCursor } from "./runtime-store.js";
|
|
2
2
|
/** The `runtime_tokens` columns every token query reads back, in the order `readRuntimeTokenRow` decodes. */
|
|
3
|
-
export const runtimeTokenColumns = "id, name, token_hash, allowed_actions, blocked_actions, allowed_proxies, allowed_connections, created_at, last_used_at";
|
|
3
|
+
export const runtimeTokenColumns = "id, name, token_hash, allowed_actions, blocked_actions, allowed_proxies, allowed_connections, allowed_triggers, created_at, last_used_at";
|
|
4
4
|
/** Read a column the query selected as a string, rejecting anything the schema cannot produce. */
|
|
5
5
|
export function readString(row, key) {
|
|
6
6
|
const value = row[key];
|
|
@@ -32,6 +32,7 @@ export function readRuntimeTokenRow(row) {
|
|
|
32
32
|
blockedActions: parseJson(readString(row, "blocked_actions")),
|
|
33
33
|
allowedProxies: parseJson(readString(row, "allowed_proxies")),
|
|
34
34
|
allowedConnections: parseJson(readOptionalString(row, "allowed_connections") ?? "[]"),
|
|
35
|
+
allowedTriggers: parseJson(readString(row, "allowed_triggers")),
|
|
35
36
|
createdAt: readString(row, "created_at"),
|
|
36
37
|
lastUsedAt: readOptionalString(row, "last_used_at"),
|
|
37
38
|
};
|
|
@@ -8,6 +8,7 @@ export interface RuntimeTokenRecord {
|
|
|
8
8
|
blockedActions: string[];
|
|
9
9
|
allowedProxies: string[];
|
|
10
10
|
allowedConnections: string[];
|
|
11
|
+
allowedTriggers?: string[];
|
|
11
12
|
createdAt: string;
|
|
12
13
|
lastUsedAt?: string;
|
|
13
14
|
}
|
|
@@ -18,6 +19,7 @@ export interface RuntimeTokenSummary {
|
|
|
18
19
|
blockedActions: string[];
|
|
19
20
|
allowedProxies: string[];
|
|
20
21
|
allowedConnections: string[];
|
|
22
|
+
allowedTriggers?: string[];
|
|
21
23
|
createdAt: string;
|
|
22
24
|
lastUsedAt?: string;
|
|
23
25
|
}
|
|
@@ -23,6 +23,7 @@ export class RuntimeTokenService {
|
|
|
23
23
|
blockedActions: policy.blockedActions,
|
|
24
24
|
allowedProxies: policy.allowedProxies,
|
|
25
25
|
allowedConnections: policy.allowedConnections ?? [],
|
|
26
|
+
allowedTriggers: policy.allowedTriggers ?? [],
|
|
26
27
|
createdAt: now,
|
|
27
28
|
};
|
|
28
29
|
await this.store.add(record);
|
|
@@ -54,6 +55,7 @@ export class RuntimeTokenService {
|
|
|
54
55
|
blockedActions: matched.blockedActions,
|
|
55
56
|
allowedProxies: matched.allowedProxies,
|
|
56
57
|
allowedConnections: matched.allowedConnections ?? [],
|
|
58
|
+
allowedTriggers: matched.allowedTriggers ?? [],
|
|
57
59
|
};
|
|
58
60
|
}
|
|
59
61
|
async verifyToken(token) {
|
|
@@ -83,6 +85,7 @@ export function summarizeRuntimeToken(record) {
|
|
|
83
85
|
blockedActions: record.blockedActions,
|
|
84
86
|
allowedProxies: record.allowedProxies,
|
|
85
87
|
allowedConnections: record.allowedConnections,
|
|
88
|
+
allowedTriggers: record.allowedTriggers ?? [],
|
|
86
89
|
createdAt: record.createdAt,
|
|
87
90
|
lastUsedAt: record.lastUsedAt,
|
|
88
91
|
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { StoredSaasConnection } from "../../connection-service.ts";
|
|
2
|
+
import type { ISecretCodec } from "../secrets/secret-codec-core.ts";
|
|
3
|
+
import type { RequestStatement, RequestTransaction } from "./connection-request-store.ts";
|
|
4
|
+
import type { RuntimeRow } from "./runtime-sql.ts";
|
|
5
|
+
export interface ManagedProject {
|
|
6
|
+
id: string;
|
|
7
|
+
projectId: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
apiKey: string;
|
|
10
|
+
}
|
|
11
|
+
interface OAuthSourceRecord {
|
|
12
|
+
service: string;
|
|
13
|
+
managedProjectId: string;
|
|
14
|
+
projectId: string;
|
|
15
|
+
providerConfigId: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SaasCleanup {
|
|
18
|
+
id: string;
|
|
19
|
+
managedProjectId: string;
|
|
20
|
+
providerConfigId: string;
|
|
21
|
+
externalUserId: string;
|
|
22
|
+
remoteRequestId: string | null;
|
|
23
|
+
connectedAccountId: string | null;
|
|
24
|
+
leaseId: string;
|
|
25
|
+
attempts: number;
|
|
26
|
+
service: string | null;
|
|
27
|
+
requestExpiresAt: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface InstanceSnapshot {
|
|
30
|
+
instanceId: string;
|
|
31
|
+
connections: number;
|
|
32
|
+
requests: number;
|
|
33
|
+
sources: number;
|
|
34
|
+
projects: number;
|
|
35
|
+
cleanup: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ResetInstanceInput {
|
|
38
|
+
expectedInstanceId: string;
|
|
39
|
+
newInstanceId: string;
|
|
40
|
+
}
|
|
41
|
+
/** Queue references before removing their owning rows in the same transaction. */
|
|
42
|
+
export declare function queueSaasConnections(where: string, values: RequestStatement["values"]): RequestStatement;
|
|
43
|
+
export declare function queueSaasRequests(where: string, values: RequestStatement["values"]): RequestStatement;
|
|
44
|
+
/** Persistent project identity, default sources and ordinary account deletion work. */
|
|
45
|
+
export declare class SaasProjectStore {
|
|
46
|
+
private readonly transaction;
|
|
47
|
+
private readonly codec;
|
|
48
|
+
constructor(transaction: RequestTransaction, codec: ISecretCodec);
|
|
49
|
+
getInstanceId(): Promise<string>;
|
|
50
|
+
getProject(): Promise<ManagedProject | undefined>;
|
|
51
|
+
saveProject(project: ManagedProject): Promise<boolean>;
|
|
52
|
+
deleteProject(id: string): Promise<boolean>;
|
|
53
|
+
listSources(): Promise<OAuthSourceRecord[]>;
|
|
54
|
+
getSource(service: string): Promise<{
|
|
55
|
+
managedProjectId: string;
|
|
56
|
+
providerConfigId: string;
|
|
57
|
+
} | undefined>;
|
|
58
|
+
setSource(service: string, source: {
|
|
59
|
+
managedProjectId: string;
|
|
60
|
+
providerConfigId: string;
|
|
61
|
+
} | undefined): Promise<boolean>;
|
|
62
|
+
getCleanupStats(): Promise<{
|
|
63
|
+
pending: number;
|
|
64
|
+
manual: number;
|
|
65
|
+
paused: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
claimCleanup(now: number, leaseMs?: number): Promise<SaasCleanup | undefined>;
|
|
68
|
+
saveCleanupAccount(task: SaasCleanup, accountId: string): Promise<boolean>;
|
|
69
|
+
pauseCleanup(task: SaasCleanup, rejectedKey: string): Promise<void>;
|
|
70
|
+
inspectInstance(): Promise<InstanceSnapshot>;
|
|
71
|
+
/** Offline clone maintenance: every delete is guarded by the old identity in the same atomic batch. */
|
|
72
|
+
resetInstance(input: ResetInstanceInput): Promise<"reset" | "already_reset" | "conflict">;
|
|
73
|
+
finishCleanup(task: SaasCleanup): Promise<boolean>;
|
|
74
|
+
retryCleanup(task: SaasCleanup, nextAttemptAt: number, errorCode: string, manual?: boolean): Promise<boolean>;
|
|
75
|
+
}
|
|
76
|
+
export declare function readSaasConnection(row: RuntimeRow, codec: ISecretCodec): Promise<StoredSaasConnection>;
|
|
77
|
+
export {};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/** Queue references before removing their owning rows in the same transaction. */
|
|
2
|
+
export function queueSaasConnections(where, values) {
|
|
3
|
+
return {
|
|
4
|
+
sql: `insert into saas_cleanup
|
|
5
|
+
(id, managed_project_id, provider_config_id, external_user_id, remote_account_id, created_at, service)
|
|
6
|
+
select 'account:' || managed_project_id || ':' || remote_account_id,
|
|
7
|
+
managed_project_id, provider_config_id, external_user_id, remote_account_id, ?, service
|
|
8
|
+
from connections where source = 'saas' and (${where})
|
|
9
|
+
on conflict (id) do nothing`,
|
|
10
|
+
values: [Date.now(), ...values],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function queueSaasRequests(where, values) {
|
|
14
|
+
return {
|
|
15
|
+
sql: `insert into saas_cleanup
|
|
16
|
+
(id, managed_project_id, provider_config_id, external_user_id, remote_request_id, remote_account_id, status, created_at, service, request_expires_at)
|
|
17
|
+
select 'request:' || id, managed_project_id, provider_config_id, external_user_id,
|
|
18
|
+
remote_request_id, remote_account_id,
|
|
19
|
+
case when remote_request_id is null and remote_account_id is null then 'manual' else 'pending' end, ?, service, expires_at
|
|
20
|
+
from connection_requests where kind = 'saas' and phase <> 'completed' and (${where})
|
|
21
|
+
on conflict (id) do nothing`,
|
|
22
|
+
values: [Date.now(), ...values],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Persistent project identity, default sources and ordinary account deletion work. */
|
|
26
|
+
export class SaasProjectStore {
|
|
27
|
+
transaction;
|
|
28
|
+
codec;
|
|
29
|
+
constructor(transaction, codec) {
|
|
30
|
+
this.transaction = transaction;
|
|
31
|
+
this.codec = codec;
|
|
32
|
+
}
|
|
33
|
+
async getInstanceId() {
|
|
34
|
+
const [, [row]] = await this.transaction([
|
|
35
|
+
{
|
|
36
|
+
sql: "insert into instance_identity (id, instance_id) values (1, ?) on conflict (id) do nothing",
|
|
37
|
+
values: [crypto.randomUUID()],
|
|
38
|
+
},
|
|
39
|
+
{ sql: "select instance_id from instance_identity where id = 1", values: [] },
|
|
40
|
+
]);
|
|
41
|
+
return row.instance_id;
|
|
42
|
+
}
|
|
43
|
+
async getProject() {
|
|
44
|
+
const [[row]] = await this.transaction([
|
|
45
|
+
{ sql: "select managed_project_id, project_id, base_url, value from managed_project where id = 1", values: [] },
|
|
46
|
+
]);
|
|
47
|
+
return row
|
|
48
|
+
? {
|
|
49
|
+
id: row.managed_project_id,
|
|
50
|
+
projectId: row.project_id,
|
|
51
|
+
baseUrl: row.base_url,
|
|
52
|
+
apiKey: await this.codec.decode(row.value),
|
|
53
|
+
}
|
|
54
|
+
: undefined;
|
|
55
|
+
}
|
|
56
|
+
async saveProject(project) {
|
|
57
|
+
if (!this.codec.encrypted)
|
|
58
|
+
throw new Error("SaaS project configuration requires encrypted storage.");
|
|
59
|
+
const value = await this.codec.encode(project.apiKey);
|
|
60
|
+
const [[row]] = await this.transaction([
|
|
61
|
+
{
|
|
62
|
+
sql: `insert into managed_project (id, managed_project_id, project_id, base_url, value)
|
|
63
|
+
values (1, ?, ?, ?, ?) on conflict (id) do update set value = excluded.value, cleanup_paused = 0
|
|
64
|
+
where managed_project.managed_project_id = excluded.managed_project_id
|
|
65
|
+
and managed_project.project_id = excluded.project_id and managed_project.base_url = excluded.base_url
|
|
66
|
+
returning managed_project_id`,
|
|
67
|
+
values: [project.id, project.projectId, project.baseUrl, value],
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
return row !== undefined;
|
|
71
|
+
}
|
|
72
|
+
async deleteProject(id) {
|
|
73
|
+
const [[row]] = await this.transaction([
|
|
74
|
+
{
|
|
75
|
+
sql: `delete from managed_project where managed_project_id = ?
|
|
76
|
+
and not exists (select 1 from oauth_sources where managed_project_id = ?)
|
|
77
|
+
and not exists (select 1 from connections where managed_project_id = ?)
|
|
78
|
+
and not exists (select 1 from connection_requests where managed_project_id = ? and phase <> 'completed')
|
|
79
|
+
and not exists (select 1 from saas_cleanup where managed_project_id = ?) returning id`,
|
|
80
|
+
values: [id, id, id, id, id],
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
return row !== undefined;
|
|
84
|
+
}
|
|
85
|
+
async listSources() {
|
|
86
|
+
const [rows] = await this.transaction([
|
|
87
|
+
{
|
|
88
|
+
sql: `select s.service, s.managed_project_id, p.project_id, s.provider_config_id
|
|
89
|
+
from oauth_sources s join managed_project p on p.managed_project_id = s.managed_project_id`,
|
|
90
|
+
values: [],
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
return rows.map((row) => ({
|
|
94
|
+
service: row.service,
|
|
95
|
+
managedProjectId: row.managed_project_id,
|
|
96
|
+
projectId: row.project_id,
|
|
97
|
+
providerConfigId: row.provider_config_id,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
async getSource(service) {
|
|
101
|
+
const [[row]] = await this.transaction([
|
|
102
|
+
{ sql: "select managed_project_id, provider_config_id from oauth_sources where service = ?", values: [service] },
|
|
103
|
+
]);
|
|
104
|
+
return row
|
|
105
|
+
? { managedProjectId: row.managed_project_id, providerConfigId: row.provider_config_id }
|
|
106
|
+
: undefined;
|
|
107
|
+
}
|
|
108
|
+
async setSource(service, source) {
|
|
109
|
+
if (!source) {
|
|
110
|
+
await this.transaction([{ sql: "delete from oauth_sources where service = ?", values: [service] }]);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
const [[row]] = await this.transaction([
|
|
114
|
+
{
|
|
115
|
+
sql: `insert into oauth_sources (service, managed_project_id, provider_config_id)
|
|
116
|
+
select ?, ?, ? where exists (select 1 from managed_project where managed_project_id = ?)
|
|
117
|
+
on conflict (service) do update set managed_project_id = excluded.managed_project_id,
|
|
118
|
+
provider_config_id = excluded.provider_config_id returning service`,
|
|
119
|
+
values: [service, source.managedProjectId, source.providerConfigId, source.managedProjectId],
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
return row !== undefined;
|
|
123
|
+
}
|
|
124
|
+
async getCleanupStats() {
|
|
125
|
+
const [rows, [project]] = await this.transaction([
|
|
126
|
+
{ sql: "select status, count(*) as count from saas_cleanup group by status", values: [] },
|
|
127
|
+
{ sql: "select cleanup_paused from managed_project where id = 1", values: [] },
|
|
128
|
+
]);
|
|
129
|
+
return {
|
|
130
|
+
paused: project?.cleanup_paused === 1,
|
|
131
|
+
pending: Number(rows.find((row) => row.status === "pending")?.count ?? 0),
|
|
132
|
+
manual: Number(rows.find((row) => row.status === "manual")?.count ?? 0),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
async claimCleanup(now, leaseMs = 45_000) {
|
|
136
|
+
const leaseId = crypto.randomUUID();
|
|
137
|
+
const [[row]] = await this.transaction([
|
|
138
|
+
{
|
|
139
|
+
sql: `update saas_cleanup set lease_id = ?, lease_until = ?
|
|
140
|
+
where id = (select id from saas_cleanup where status = 'pending' and next_attempt_at <= ?
|
|
141
|
+
and exists (select 1 from managed_project where managed_project_id = saas_cleanup.managed_project_id and cleanup_paused = 0)
|
|
142
|
+
and (lease_until is null or lease_until <= ?) order by created_at, id limit 1)
|
|
143
|
+
and (lease_until is null or lease_until <= ?) returning *`,
|
|
144
|
+
values: [leaseId, now + leaseMs, now, now, now],
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
return row
|
|
148
|
+
? {
|
|
149
|
+
id: row.id,
|
|
150
|
+
managedProjectId: row.managed_project_id,
|
|
151
|
+
providerConfigId: row.provider_config_id,
|
|
152
|
+
externalUserId: row.external_user_id,
|
|
153
|
+
remoteRequestId: row.remote_request_id,
|
|
154
|
+
connectedAccountId: row.remote_account_id,
|
|
155
|
+
leaseId,
|
|
156
|
+
attempts: Number(row.attempts),
|
|
157
|
+
service: row.service,
|
|
158
|
+
requestExpiresAt: row.request_expires_at,
|
|
159
|
+
}
|
|
160
|
+
: undefined;
|
|
161
|
+
}
|
|
162
|
+
async saveCleanupAccount(task, accountId) {
|
|
163
|
+
const [[row]] = await this.transaction([
|
|
164
|
+
{
|
|
165
|
+
sql: "update saas_cleanup set remote_account_id = ? where id = ? and lease_id = ? and lease_until > ? returning id",
|
|
166
|
+
values: [accountId, task.id, task.leaseId, Date.now()],
|
|
167
|
+
},
|
|
168
|
+
]);
|
|
169
|
+
return row !== undefined;
|
|
170
|
+
}
|
|
171
|
+
async pauseCleanup(task, rejectedKey) {
|
|
172
|
+
const [[project]] = await this.transaction([
|
|
173
|
+
{
|
|
174
|
+
sql: "select value from managed_project where managed_project_id = ?",
|
|
175
|
+
values: [task.managedProjectId],
|
|
176
|
+
},
|
|
177
|
+
]);
|
|
178
|
+
if (!project || (await this.codec.decode(project.value)) !== rejectedKey)
|
|
179
|
+
return;
|
|
180
|
+
await this.transaction([
|
|
181
|
+
{
|
|
182
|
+
sql: `update managed_project set cleanup_paused = 1 where managed_project_id = ? and value = ?
|
|
183
|
+
and exists (select 1 from saas_cleanup where id = ? and lease_id = ? and lease_until > ?)`,
|
|
184
|
+
values: [task.managedProjectId, project.value, task.id, task.leaseId, Date.now()],
|
|
185
|
+
},
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
async inspectInstance() {
|
|
189
|
+
await this.getInstanceId();
|
|
190
|
+
const [[row]] = await this.transaction([
|
|
191
|
+
{
|
|
192
|
+
sql: `select instance_id,
|
|
193
|
+
(select count(*) from connections where source = 'saas') as connections,
|
|
194
|
+
(select count(*) from connection_requests where kind = 'saas') as requests,
|
|
195
|
+
(select count(*) from oauth_sources) as sources,
|
|
196
|
+
(select count(*) from managed_project) as projects,
|
|
197
|
+
(select count(*) from saas_cleanup) as cleanup
|
|
198
|
+
from instance_identity where id = 1`,
|
|
199
|
+
values: [],
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
202
|
+
return {
|
|
203
|
+
instanceId: row.instance_id,
|
|
204
|
+
connections: Number(row.connections),
|
|
205
|
+
requests: Number(row.requests),
|
|
206
|
+
sources: Number(row.sources),
|
|
207
|
+
projects: Number(row.projects),
|
|
208
|
+
cleanup: Number(row.cleanup),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/** Offline clone maintenance: every delete is guarded by the old identity in the same atomic batch. */
|
|
212
|
+
async resetInstance(input) {
|
|
213
|
+
if (!input.expectedInstanceId || !input.newInstanceId || input.expectedInstanceId === input.newInstanceId)
|
|
214
|
+
throw new Error("Instance reset requires distinct non-empty old and new identities.");
|
|
215
|
+
const guard = "exists (select 1 from instance_identity where id = 1 and instance_id = ?)";
|
|
216
|
+
const results = await this.transaction([
|
|
217
|
+
...[
|
|
218
|
+
"delete from connections where source = 'saas' and",
|
|
219
|
+
"delete from connection_requests where kind = 'saas' and",
|
|
220
|
+
"delete from oauth_sources where",
|
|
221
|
+
"delete from saas_cleanup where",
|
|
222
|
+
"delete from managed_project where",
|
|
223
|
+
].map((sql) => ({ sql: `${sql} ${guard}`, values: [input.expectedInstanceId] })),
|
|
224
|
+
{
|
|
225
|
+
sql: "update instance_identity set instance_id = ? where id = 1 and instance_id = ? returning instance_id",
|
|
226
|
+
values: [input.newInstanceId, input.expectedInstanceId],
|
|
227
|
+
},
|
|
228
|
+
{ sql: "select instance_id from instance_identity where id = 1", values: [] },
|
|
229
|
+
]);
|
|
230
|
+
if (results[5].length)
|
|
231
|
+
return "reset";
|
|
232
|
+
return results[6][0]?.instance_id === input.newInstanceId ? "already_reset" : "conflict";
|
|
233
|
+
}
|
|
234
|
+
async finishCleanup(task) {
|
|
235
|
+
const [[row]] = await this.transaction([
|
|
236
|
+
{
|
|
237
|
+
sql: "delete from saas_cleanup where id = ? and lease_id = ? and lease_until > ? returning id",
|
|
238
|
+
values: [task.id, task.leaseId, Date.now()],
|
|
239
|
+
},
|
|
240
|
+
]);
|
|
241
|
+
return row !== undefined;
|
|
242
|
+
}
|
|
243
|
+
async retryCleanup(task, nextAttemptAt, errorCode, manual = false) {
|
|
244
|
+
const [[row]] = await this.transaction([
|
|
245
|
+
{
|
|
246
|
+
sql: `update saas_cleanup set lease_id = null, lease_until = null, attempts = attempts + 1,
|
|
247
|
+
next_attempt_at = ?, error_code = ?, status = ? where id = ? and lease_id = ? and lease_until > ? returning id`,
|
|
248
|
+
values: [nextAttemptAt, errorCode, manual ? "manual" : "pending", task.id, task.leaseId, Date.now()],
|
|
249
|
+
},
|
|
250
|
+
]);
|
|
251
|
+
return row !== undefined;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
export async function readSaasConnection(row, codec) {
|
|
255
|
+
const display = JSON.parse(await codec.decode(row.value));
|
|
256
|
+
return {
|
|
257
|
+
source: "saas",
|
|
258
|
+
id: row.id,
|
|
259
|
+
revision: row.revision,
|
|
260
|
+
service: row.service,
|
|
261
|
+
connectionName: row.connection_name,
|
|
262
|
+
reference: {
|
|
263
|
+
managedProjectId: row.managed_project_id,
|
|
264
|
+
providerConfigId: row.provider_config_id,
|
|
265
|
+
externalUserId: row.external_user_id,
|
|
266
|
+
connectedAccountId: row.remote_account_id,
|
|
267
|
+
localRequestId: row.local_request_id,
|
|
268
|
+
},
|
|
269
|
+
profile: display.profile,
|
|
270
|
+
status: display.status,
|
|
271
|
+
comment: display.comment,
|
|
272
|
+
};
|
|
273
|
+
}
|