@oomol-lab/open-connector 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/assets/open-connector/catalog/apps/airtable.json +134 -0
- package/assets/open-connector/catalog/apps/aisa.json +916 -76
- package/assets/open-connector/catalog/apps/cal.json +24 -6
- package/assets/open-connector/catalog/apps/discordbot.json +2 -2
- 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/github.json +275 -0
- package/assets/open-connector/catalog/apps/gitlab.json +125 -0
- package/assets/open-connector/catalog/apps/gmail.json +151 -0
- package/assets/open-connector/catalog/apps/googlecalendar.json +206 -0
- package/assets/open-connector/catalog/apps/googledrive.json +479 -0
- package/assets/open-connector/catalog/apps/googlesheets.json +144 -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/linear.json +116 -0
- package/assets/open-connector/catalog/apps/notion.json +142 -0
- package/assets/open-connector/catalog/apps/one_drive.json +185 -0
- package/assets/open-connector/catalog/apps/outlook.json +182 -0
- package/assets/open-connector/catalog/apps/shopify.json +282 -0
- package/assets/open-connector/catalog/apps/slack.json +182 -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/weixin_store.json +543 -2
- package/assets/open-connector/catalog/apps/woocommerce.json +127 -0
- package/assets/open-connector/catalog/apps/zendesk.json +152 -0
- package/assets/open-connector/catalog/apps/zerotier.json +9 -9
- 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 +3 -0
- package/src/core/cast.js +4 -1
- package/src/core/guarded-fetch.d.ts +5 -0
- package/src/core/guarded-fetch.js +13 -4
- 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 +7 -0
- package/src/core/types.d.ts +4 -0
- package/src/marketplace/marketplace-service.d.ts +0 -1
- package/src/marketplace/marketplace-service.js +80 -92
- package/src/mcp.js +19 -5
- package/src/oauth/oauth-flow-service.d.ts +8 -1
- package/src/oauth/oauth-flow-service.js +10 -4
- package/src/providers/action-contracts.generated.d.ts +4 -2
- 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 +196 -22
- package/src/providers/cal/actions.js +5 -1
- package/src/providers/enormail/executors.d.ts +4 -0
- package/src/providers/enormail/executors.js +97 -0
- 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/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 +2 -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/googlecalendar/executors.d.ts +3 -0
- package/src/providers/googlecalendar/executors.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/googledrive/executors.d.ts +3 -0
- package/src/providers/googledrive/executors.js +7 -0
- 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/googlesheets/executors.d.ts +3 -0
- package/src/providers/googlesheets/executors.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/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/linear/executors.d.ts +3 -0
- package/src/providers/linear/executors.js +2 -0
- 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/notion/executors.d.ts +3 -0
- package/src/providers/notion/executors.js +2 -0
- 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/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 +2 -0
- 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 +6 -0
- package/src/providers/provider-loader.d.ts +5 -0
- package/src/providers/provider-loader.js +4 -0
- package/src/providers/registry.generated.js +2 -0
- 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/executors.d.ts +3 -0
- package/src/providers/slack/executors.js +2 -0
- 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/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/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/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/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/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 +112 -14
- package/src/server/api/policy-input.js +6 -0
- package/src/server/api/runtime-api.d.ts +10 -2
- package/src/server/api/runtime-api.js +17 -4
- 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 +147 -13
- 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/server/storage/postgres-runtime-store.d.ts +0 -39
|
@@ -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
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
import type { IntegrationDefinition } from "../../triggers/common/integration.ts";
|
|
3
|
+
import type { PollDefinition } from "../../triggers/common/poll.ts";
|
|
2
4
|
import type { ProviderActionHandlers } from "../provider-runtime.ts";
|
|
3
5
|
import type { OAuthProviderContext } from "../provider-runtime.ts";
|
|
4
6
|
type OneDriveRuntimeDeps = OAuthProviderContext;
|
|
@@ -23,4 +25,5 @@ export declare const proxy: ProviderProxyExecutor;
|
|
|
23
25
|
export declare const credentialValidators: CredentialValidators;
|
|
24
26
|
export declare function oneDriveJsonRequest<T>(pathOrUrl: string, input: OneDriveRequestInput): Promise<T>;
|
|
25
27
|
export declare function assertOneDriveResponse(response: Response): Promise<void>;
|
|
28
|
+
export declare const triggers: readonly (IntegrationDefinition | PollDefinition)[];
|
|
26
29
|
export {};
|
|
@@ -2,6 +2,7 @@ import { Buffer } from "node:buffer";
|
|
|
2
2
|
import { compactObject, requiredRecord } from "../../core/cast.js";
|
|
3
3
|
import { readBoundedResponseBytes } from "../../core/request.js";
|
|
4
4
|
import { defineOAuthProviderExecutors, defineProviderProxy, ProviderRequestError, readTransitFileInput, } from "../provider-runtime.js";
|
|
5
|
+
import { oneDriveItemChanged } from "./trigger-on-item-changed.js";
|
|
5
6
|
const graphBaseUrl = "https://graph.microsoft.com/v1.0";
|
|
6
7
|
const graphOrigin = new URL(graphBaseUrl).origin;
|
|
7
8
|
const oneDriveUploadChunkSizeBytes = 10 * 1024 * 1024;
|
|
@@ -1194,3 +1195,4 @@ function toArrayBuffer(bytes) {
|
|
|
1194
1195
|
}
|
|
1195
1196
|
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
1196
1197
|
}
|
|
1198
|
+
export const triggers = [oneDriveItemChanged];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsonSchema as s } from "../../core/json-schema.js";
|
|
2
|
+
const eventSchema = s.object({
|
|
3
|
+
changeType: s.stringEnum(["created", "updated", "deleted"]),
|
|
4
|
+
createdDateTime: { type: ["string", "null"] },
|
|
5
|
+
driveId: { type: ["string", "null"] },
|
|
6
|
+
eTag: { type: ["string", "null"] },
|
|
7
|
+
itemId: s.string(),
|
|
8
|
+
itemType: s.stringEnum(["file", "folder"]),
|
|
9
|
+
lastModifiedDateTime: { type: ["string", "null"] },
|
|
10
|
+
mimeType: { type: ["string", "null"] },
|
|
11
|
+
name: s.string(),
|
|
12
|
+
parentFolderId: { type: ["string", "null"] },
|
|
13
|
+
size: { type: ["number", "null"] },
|
|
14
|
+
webUrl: s.string(),
|
|
15
|
+
}, {
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
required: [
|
|
18
|
+
"itemId",
|
|
19
|
+
"name",
|
|
20
|
+
"changeType",
|
|
21
|
+
"itemType",
|
|
22
|
+
"size",
|
|
23
|
+
"mimeType",
|
|
24
|
+
"webUrl",
|
|
25
|
+
"parentFolderId",
|
|
26
|
+
"driveId",
|
|
27
|
+
"createdDateTime",
|
|
28
|
+
"lastModifiedDateTime",
|
|
29
|
+
"eTag",
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
export const snapshot = {
|
|
33
|
+
configInputs: [
|
|
34
|
+
{
|
|
35
|
+
handle: "events",
|
|
36
|
+
jsonSchema: s.array(s.stringEnum(["created", "updated", "deleted"]), { minItems: 1, uniqueItems: true }),
|
|
37
|
+
nullable: false,
|
|
38
|
+
value: ["created", "updated"],
|
|
39
|
+
},
|
|
40
|
+
{ handle: "itemId", jsonSchema: s.string(), nullable: false, value: "" },
|
|
41
|
+
{
|
|
42
|
+
handle: "itemTypes",
|
|
43
|
+
jsonSchema: s.array(s.stringEnum(["file", "folder"]), { minItems: 1, uniqueItems: true }),
|
|
44
|
+
nullable: false,
|
|
45
|
+
value: ["file"],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
handle: "maxItemsPerPoll",
|
|
49
|
+
jsonSchema: s.integer({ maximum: 200, minimum: 1 }),
|
|
50
|
+
nullable: false,
|
|
51
|
+
value: 50,
|
|
52
|
+
},
|
|
53
|
+
{ handle: "parentFolderId", jsonSchema: s.string(), nullable: false, value: "" },
|
|
54
|
+
],
|
|
55
|
+
definitionVersion: 2,
|
|
56
|
+
description: "Polls the OneDrive change feed and triggers when a file or folder is created, updated or deleted.",
|
|
57
|
+
displayName: "File or Folder Changed",
|
|
58
|
+
key: "one_drive.on_item_changed",
|
|
59
|
+
name: "on_item_changed",
|
|
60
|
+
outputs: [{ handle: "events", jsonSchema: s.array(eventSchema), nullable: false }],
|
|
61
|
+
provider: "one_drive",
|
|
62
|
+
type: "poll",
|
|
63
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { canonicalJsonBytes, digestBytes } from "../../triggers/common/encoding.js";
|
|
2
|
+
import { eventsPollOutputs, maximumPollEventsPerPage, PermanentPollError, PollConnectionError, TransientPollError, } from "../../triggers/common/poll.js";
|
|
3
|
+
import { snapshot } from "./trigger-on-item-changed.definition.js";
|
|
4
|
+
export const oneDriveItemChanged = {
|
|
5
|
+
buildOutputs: eventsPollOutputs,
|
|
6
|
+
snapshot,
|
|
7
|
+
async poll(context) {
|
|
8
|
+
const config = resolveConfig(context.config);
|
|
9
|
+
if (context.checkpoint === null)
|
|
10
|
+
return { checkpoint: (await seed(context, config)), events: [] };
|
|
11
|
+
const checkpoint = readCheckpoint(context.checkpoint);
|
|
12
|
+
const { items, next } = await changedItems(context, checkpoint, config.maxItemsPerPoll);
|
|
13
|
+
const events = [];
|
|
14
|
+
let filtered = 0;
|
|
15
|
+
for (const [id, item] of items) {
|
|
16
|
+
const result = await evaluate(id, item, config, checkpoint);
|
|
17
|
+
if (result == "structural")
|
|
18
|
+
continue;
|
|
19
|
+
if (result == "filtered")
|
|
20
|
+
filtered += 1;
|
|
21
|
+
else
|
|
22
|
+
events.push(result);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
checkpoint: next.checkpoint,
|
|
26
|
+
events,
|
|
27
|
+
filtered,
|
|
28
|
+
...(next.hasMore ? { hasMore: true } : {}),
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
function resolveConfig(value) {
|
|
33
|
+
return {
|
|
34
|
+
events: value.events,
|
|
35
|
+
itemId: value.itemId.trim(),
|
|
36
|
+
itemTypes: value.itemTypes,
|
|
37
|
+
maxItemsPerPoll: value.maxItemsPerPoll,
|
|
38
|
+
parentFolderId: value.parentFolderId.trim(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function seed(context, config) {
|
|
42
|
+
const result = await get(context, "/me/drive/root/delta", { token: "latest" });
|
|
43
|
+
if (result.status == 404)
|
|
44
|
+
throw new PermanentPollError("OneDrive is not provisioned for this account.");
|
|
45
|
+
success(result, "delta seeding");
|
|
46
|
+
const link = record(result.data)?.["@odata.deltaLink"];
|
|
47
|
+
const token = link == null ? null : parseToken(link);
|
|
48
|
+
if (token == null)
|
|
49
|
+
throw new TransientPollError("OneDrive delta seeding response has no delta token.");
|
|
50
|
+
await validateItem(context, "parentFolderId", config.parentFolderId);
|
|
51
|
+
await validateItem(context, "itemId", config.itemId);
|
|
52
|
+
return { deltaToken: token, lastPolledAt: context.now.toISOString() };
|
|
53
|
+
}
|
|
54
|
+
async function validateItem(context, field, id) {
|
|
55
|
+
if (id.length == 0)
|
|
56
|
+
return;
|
|
57
|
+
const result = await get(context, `/me/drive/items/${encodeURIComponent(id)}`, {});
|
|
58
|
+
if (result.status == 400 || result.status == 404)
|
|
59
|
+
throw new PermanentPollError(`OneDrive ${field} does not identify an item in this drive.`);
|
|
60
|
+
success(result, `${field} validation`);
|
|
61
|
+
}
|
|
62
|
+
function readCheckpoint(value) {
|
|
63
|
+
const checkpoint = record(value);
|
|
64
|
+
if (typeof checkpoint?.deltaToken != "string" ||
|
|
65
|
+
checkpoint.deltaToken.length == 0 ||
|
|
66
|
+
typeof checkpoint.lastPolledAt != "string" ||
|
|
67
|
+
Number.isNaN(Date.parse(checkpoint.lastPolledAt))) {
|
|
68
|
+
throw new PermanentPollError("OneDrive checkpoint is invalid; recreate the Trigger.");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
deltaToken: checkpoint.deltaToken,
|
|
72
|
+
lastPolledAt: checkpoint.lastPolledAt,
|
|
73
|
+
...(typeof checkpoint.pageToken == "string" && checkpoint.pageToken.length > 0
|
|
74
|
+
? { pageToken: checkpoint.pageToken }
|
|
75
|
+
: {}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function changedItems(context, checkpoint, pageSize) {
|
|
79
|
+
const items = new Map();
|
|
80
|
+
const result = await get(context, "/me/drive/root/delta", {
|
|
81
|
+
$top: Math.min(pageSize, maximumPollEventsPerPage),
|
|
82
|
+
token: checkpoint.pageToken ?? checkpoint.deltaToken,
|
|
83
|
+
});
|
|
84
|
+
deltaSuccess(result);
|
|
85
|
+
const parsed = (record(result.data) ?? {});
|
|
86
|
+
for (const item of parsed.value ?? [])
|
|
87
|
+
if (item.id != null && item.id.length > 0)
|
|
88
|
+
items.set(item.id, item);
|
|
89
|
+
if (parsed["@odata.deltaLink"]) {
|
|
90
|
+
return {
|
|
91
|
+
items,
|
|
92
|
+
next: {
|
|
93
|
+
checkpoint: {
|
|
94
|
+
deltaToken: requireToken(parsed["@odata.deltaLink"]),
|
|
95
|
+
lastPolledAt: context.now.toISOString(),
|
|
96
|
+
},
|
|
97
|
+
hasMore: false,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (!parsed["@odata.nextLink"])
|
|
102
|
+
throw new TransientPollError("OneDrive delta response has no continuation link.");
|
|
103
|
+
return {
|
|
104
|
+
items,
|
|
105
|
+
next: {
|
|
106
|
+
checkpoint: {
|
|
107
|
+
deltaToken: checkpoint.deltaToken,
|
|
108
|
+
lastPolledAt: checkpoint.lastPolledAt,
|
|
109
|
+
pageToken: requireToken(parsed["@odata.nextLink"]),
|
|
110
|
+
},
|
|
111
|
+
hasMore: true,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async function evaluate(id, item, config, checkpoint) {
|
|
116
|
+
if (item.root != null)
|
|
117
|
+
return "structural";
|
|
118
|
+
const itemType = type(item);
|
|
119
|
+
if (itemType == null)
|
|
120
|
+
return "structural";
|
|
121
|
+
const change = item.deleted != null
|
|
122
|
+
? "deleted"
|
|
123
|
+
: createdAfter(item.createdDateTime, new Date(checkpoint.lastPolledAt))
|
|
124
|
+
? "created"
|
|
125
|
+
: "updated";
|
|
126
|
+
if (!config.events.includes(change) || !config.itemTypes.includes(itemType))
|
|
127
|
+
return "filtered";
|
|
128
|
+
if (config.parentFolderId.length > 0 && item.parentReference?.id !== config.parentFolderId)
|
|
129
|
+
return "filtered";
|
|
130
|
+
if (config.itemId.length > 0 && id !== config.itemId)
|
|
131
|
+
return "filtered";
|
|
132
|
+
return await event(id, item, change, itemType, checkpoint.deltaToken);
|
|
133
|
+
}
|
|
134
|
+
function type(item) {
|
|
135
|
+
if (item.file != null)
|
|
136
|
+
return "file";
|
|
137
|
+
if (item.folder != null)
|
|
138
|
+
return "folder";
|
|
139
|
+
return item.deleted != null ? "file" : null;
|
|
140
|
+
}
|
|
141
|
+
async function event(id, item, change, itemType, deltaToken) {
|
|
142
|
+
// 同一轮分页共用删除事件标识,后续 delta 周期必须使用新标识。
|
|
143
|
+
return {
|
|
144
|
+
dedupeKey: item.deleted != null
|
|
145
|
+
? await digestBytes(canonicalJsonBytes(["one-drive-deleted", deltaToken, id]))
|
|
146
|
+
: `${id}:${item.eTag ?? item.lastModifiedDateTime}`,
|
|
147
|
+
payload: {
|
|
148
|
+
changeType: change,
|
|
149
|
+
createdDateTime: item.createdDateTime ?? item.fileSystemInfo?.createdDateTime ?? null,
|
|
150
|
+
driveId: item.parentReference?.driveId ?? null,
|
|
151
|
+
eTag: item.eTag ?? null,
|
|
152
|
+
itemId: id,
|
|
153
|
+
itemType,
|
|
154
|
+
lastModifiedDateTime: item.lastModifiedDateTime ?? item.fileSystemInfo?.lastModifiedDateTime ?? null,
|
|
155
|
+
mimeType: item.file?.mimeType ?? null,
|
|
156
|
+
name: item.name ?? "",
|
|
157
|
+
parentFolderId: item.parentReference?.id ?? null,
|
|
158
|
+
size: item.size ?? null,
|
|
159
|
+
webUrl: item.webUrl ?? "",
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async function get(context, endpoint, query) {
|
|
164
|
+
try {
|
|
165
|
+
return await context.connector.execute({ endpoint, method: "GET", query }, context.signal);
|
|
166
|
+
}
|
|
167
|
+
catch (cause) {
|
|
168
|
+
throw new TransientPollError(`OneDrive proxy request to ${endpoint} failed.`, { cause });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function deltaSuccess(result) {
|
|
172
|
+
if (result.status == 410)
|
|
173
|
+
throw new PermanentPollError("OneDrive delta token expired; recreate the Trigger.");
|
|
174
|
+
if (result.status == 404)
|
|
175
|
+
throw new PermanentPollError("OneDrive is not provisioned for this account.");
|
|
176
|
+
if (result.status == 400)
|
|
177
|
+
throw new PermanentPollError("OneDrive rejected the delta token; recreate the Trigger.");
|
|
178
|
+
success(result, "delta list");
|
|
179
|
+
}
|
|
180
|
+
function success(result, operation) {
|
|
181
|
+
if (result.status >= 200 && result.status < 300)
|
|
182
|
+
return;
|
|
183
|
+
if (result.status == 401 || result.status == 403)
|
|
184
|
+
throw new PollConnectionError(`OneDrive ${operation} rejected the Connection.`);
|
|
185
|
+
throw new TransientPollError(`OneDrive ${operation} failed with status ${result.status}.`);
|
|
186
|
+
}
|
|
187
|
+
function requireToken(link) {
|
|
188
|
+
const token = parseToken(link);
|
|
189
|
+
if (token == null)
|
|
190
|
+
throw new TransientPollError("OneDrive delta link has no token.");
|
|
191
|
+
return token;
|
|
192
|
+
}
|
|
193
|
+
function parseToken(link) {
|
|
194
|
+
const raw = /[?&]token=([^&#]+)/.exec(link)?.[1] ?? /\(token='([^']+)'\)/.exec(link)?.[1];
|
|
195
|
+
if (raw == null)
|
|
196
|
+
return null;
|
|
197
|
+
try {
|
|
198
|
+
return decodeURIComponent(raw);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return raw;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function createdAfter(value, boundary) {
|
|
205
|
+
if (value == null || value.length == 0)
|
|
206
|
+
return false;
|
|
207
|
+
const date = new Date(value);
|
|
208
|
+
return !Number.isNaN(date.getTime()) && date >= boundary;
|
|
209
|
+
}
|
|
210
|
+
function record(value) {
|
|
211
|
+
return value != null && typeof value == "object" && !Array.isArray(value)
|
|
212
|
+
? value
|
|
213
|
+
: undefined;
|
|
214
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
import type { IntegrationDefinition } from "../../triggers/common/integration.ts";
|
|
3
|
+
import type { PollDefinition } from "../../triggers/common/poll.ts";
|
|
2
4
|
export declare const proxy: ProviderProxyExecutor;
|
|
3
5
|
interface OutlookRequestInput {
|
|
4
6
|
accessToken: string;
|
|
@@ -13,4 +15,5 @@ interface OutlookRequestInput {
|
|
|
13
15
|
export declare const executors: ProviderExecutors;
|
|
14
16
|
export declare const credentialValidators: CredentialValidators;
|
|
15
17
|
export declare function outlookJsonRequest<T>(pathOrUrl: string, input: OutlookRequestInput): Promise<T>;
|
|
18
|
+
export declare const triggers: readonly (IntegrationDefinition | PollDefinition)[];
|
|
16
19
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { compactObject, requiredRecord } from "../../core/cast.js";
|
|
2
2
|
import { defineOAuthProviderExecutors, defineProviderProxy, providerInputError, ProviderRequestError, } from "../provider-runtime.js";
|
|
3
3
|
import { microsoftGraphJson, microsoftGraphRequest } from "./microsoft-graph.js";
|
|
4
|
+
import { outlookMessageReceived } from "./trigger-on-message-received.js";
|
|
4
5
|
const outlookGraphBaseUrl = "https://graph.microsoft.com/v1.0";
|
|
5
6
|
export const proxy = defineProviderProxy({
|
|
6
7
|
service: "outlook",
|
|
@@ -434,3 +435,4 @@ function requiredString(value, field) {
|
|
|
434
435
|
function asObject(value) {
|
|
435
436
|
return requiredRecord(value, "object input", (message) => new ProviderRequestError(400, message));
|
|
436
437
|
}
|
|
438
|
+
export const triggers = [outlookMessageReceived];
|