@tangle-network/agent-integrations 0.38.0 → 0.40.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 +2 -2
- package/dist/catalog.js +3 -3
- package/dist/{chunk-FC7GL2DI.js → chunk-4GZU3PB5.js} +6 -4
- package/dist/{chunk-FC7GL2DI.js.map → chunk-4GZU3PB5.js.map} +1 -1
- package/dist/{chunk-ZMAMOCJZ.js → chunk-4TI3WXAD.js} +1847 -1595
- package/dist/{chunk-ZMAMOCJZ.js.map → chunk-4TI3WXAD.js.map} +1 -1
- package/dist/{chunk-53NQJZAT.js → chunk-IA5GCKM6.js} +2 -3
- package/dist/chunk-IA5GCKM6.js.map +1 -0
- package/dist/connectors/adapters/index.d.ts +87 -94
- package/dist/connectors/adapters/index.js +7 -11
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +7 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -13
- package/dist/mcp.js +3 -3
- package/dist/registry.js +3 -3
- package/dist/{router-BncoovUh.d.ts → router-S0Dadv2x.d.ts} +10 -0
- package/dist/runtime.js +3 -3
- package/dist/specs.js +1 -1
- package/dist/stripe/index.d.ts +1 -1
- package/dist/webhooks/index.d.ts +14 -3
- package/dist/webhooks/index.js +128 -2
- package/dist/webhooks/index.js.map +1 -1
- package/docs/adapter-triage.md +3 -3
- package/docs/catalog-registry.md +1 -1
- package/package.json +1 -1
- package/dist/chunk-53NQJZAT.js.map +0 -1
|
@@ -196,6 +196,7 @@ __export(adapters_exports, {
|
|
|
196
196
|
gitlabConnector: () => gitlabConnector,
|
|
197
197
|
glideConnector: () => glideConnector,
|
|
198
198
|
gmail: () => gmail,
|
|
199
|
+
googleAnalyticsConnector: () => googleAnalyticsConnector,
|
|
199
200
|
googleBigqueryConnector: () => googleBigqueryConnector,
|
|
200
201
|
googleCalendar: () => googleCalendar,
|
|
201
202
|
googleCloudStorageConnector: () => googleCloudStorageConnector,
|
|
@@ -204,6 +205,7 @@ __export(adapters_exports, {
|
|
|
204
205
|
googleDrive: () => googleDrive,
|
|
205
206
|
googleForms: () => googleForms,
|
|
206
207
|
googleGeminiConnector: () => googleGeminiConnector,
|
|
208
|
+
googleMeetConnector: () => googleMeetConnector,
|
|
207
209
|
googleMyBusinessConnector: () => googleMyBusinessConnector,
|
|
208
210
|
googleSearchConnector: () => googleSearchConnector,
|
|
209
211
|
googleSearchConsoleConnector: () => googleSearchConsoleConnector,
|
|
@@ -319,12 +321,8 @@ __export(adapters_exports, {
|
|
|
319
321
|
microsoftDynamicsCrmConnector: () => microsoftDynamicsCrmConnector,
|
|
320
322
|
microsoftExcel365Connector: () => microsoftExcel365Connector,
|
|
321
323
|
microsoftGraph: () => microsoftGraph,
|
|
322
|
-
microsoftOnedriveConnector: () => microsoftOnedriveConnector,
|
|
323
324
|
microsoftOnenoteConnector: () => microsoftOnenoteConnector,
|
|
324
|
-
microsoftOutlookCalendarConnector: () => microsoftOutlookCalendarConnector,
|
|
325
|
-
microsoftOutlookConnector: () => microsoftOutlookConnector,
|
|
326
325
|
microsoftPowerBiConnector: () => microsoftPowerBiConnector,
|
|
327
|
-
microsoftSharepointConnector: () => microsoftSharepointConnector,
|
|
328
326
|
microsoftTeams: () => microsoftTeams,
|
|
329
327
|
microsoftTodoConnector: () => microsoftTodoConnector,
|
|
330
328
|
millionverifierConnector: () => millionverifierConnector,
|
|
@@ -342,8 +340,8 @@ __export(adapters_exports, {
|
|
|
342
340
|
niftyConnector: () => niftyConnector,
|
|
343
341
|
ninjapipeConnector: () => ninjapipeConnector,
|
|
344
342
|
nocodbConnector: () => nocodbConnector,
|
|
343
|
+
notion: () => notion,
|
|
345
344
|
notionConnector: () => notionConnector,
|
|
346
|
-
notionDatabase: () => notionDatabase,
|
|
347
345
|
ntfyConnector: () => ntfyConnector,
|
|
348
346
|
odooConnector: () => odooConnector,
|
|
349
347
|
omniCoConnector: () => omniCoConnector,
|
|
@@ -3134,91 +3132,253 @@ function microsoftCalendar(opts) {
|
|
|
3134
3132
|
attendees: {
|
|
3135
3133
|
type: "array",
|
|
3136
3134
|
items: { type: "string", description: "attendee email" }
|
|
3137
|
-
}
|
|
3135
|
+
},
|
|
3136
|
+
// Optional rich create fields (ported from microsoft-outlook-calendar
|
|
3137
|
+
// create.event). All additive — the freebusy pre-flight and
|
|
3138
|
+
// alternative-slot behavior below is unchanged when these are absent.
|
|
3139
|
+
calendarId: {
|
|
3140
|
+
type: "string",
|
|
3141
|
+
description: "Target calendar id; defaults to the user's primary calendar (/me/events) when omitted."
|
|
3142
|
+
},
|
|
3143
|
+
location: {
|
|
3144
|
+
type: "object",
|
|
3145
|
+
description: 'Graph location resource, e.g. { displayName: "Room 1" }.'
|
|
3146
|
+
},
|
|
3147
|
+
recurrence: {
|
|
3148
|
+
type: "object",
|
|
3149
|
+
description: "Graph patternedRecurrence resource ({ pattern, range })."
|
|
3150
|
+
},
|
|
3151
|
+
isOnlineMeeting: { type: "boolean", description: "Provision an online meeting (Teams) for the event." },
|
|
3152
|
+
onlineMeetingProvider: {
|
|
3153
|
+
type: "string",
|
|
3154
|
+
description: "Online meeting provider, e.g. 'teamsForBusiness'."
|
|
3155
|
+
},
|
|
3156
|
+
reminderMinutesBeforeStart: {
|
|
3157
|
+
type: "integer",
|
|
3158
|
+
description: "Minutes before start to fire the reminder."
|
|
3159
|
+
},
|
|
3160
|
+
isAllDay: { type: "boolean", description: "Mark the event as all-day (start/end must be midnight-aligned)." },
|
|
3161
|
+
categories: {
|
|
3162
|
+
type: "array",
|
|
3163
|
+
items: { type: "string", description: "Outlook category name" }
|
|
3164
|
+
},
|
|
3165
|
+
importance: { type: "string", description: "Event importance: 'low' | 'normal' | 'high'." }
|
|
3138
3166
|
},
|
|
3139
3167
|
required: ["start", "end", "summary"]
|
|
3140
3168
|
}
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
name: "delete_event",
|
|
3172
|
+
class: "mutation",
|
|
3173
|
+
description: "Delete an event by id from the connected Outlook calendar. Graph returns 204 on success; a re-delete of a missing event surfaces as 404 mapped to an idempotent tombstone. Honors If-Match against the event etag when the caller supplies expectedEtag.",
|
|
3174
|
+
cas: "native-idempotency",
|
|
3175
|
+
externalEffect: true,
|
|
3176
|
+
parameters: {
|
|
3177
|
+
type: "object",
|
|
3178
|
+
properties: {
|
|
3179
|
+
eventId: { type: "string", description: "Graph event id to delete." }
|
|
3180
|
+
},
|
|
3181
|
+
required: ["eventId"]
|
|
3182
|
+
}
|
|
3183
|
+
},
|
|
3184
|
+
{
|
|
3185
|
+
name: "list_events",
|
|
3186
|
+
class: "read",
|
|
3187
|
+
description: "List actual event objects on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar (/me/events) unless calendarId is supplied. Distinct from list_availability, which returns busy windows.",
|
|
3188
|
+
parameters: {
|
|
3189
|
+
type: "object",
|
|
3190
|
+
properties: {
|
|
3191
|
+
calendarId: { type: "string", description: "Calendar id; defaults to the user's primary calendar when omitted." },
|
|
3192
|
+
$top: { type: "integer", description: "Max events to return (OData page size)." },
|
|
3193
|
+
$skip: { type: "integer", description: "Number of events to skip (OData paging offset)." },
|
|
3194
|
+
$filter: { type: "string", description: "OData $filter expression." },
|
|
3195
|
+
$select: { type: "string", description: "Comma-separated event fields to project." },
|
|
3196
|
+
$orderby: { type: "string", description: "OData $orderby expression." },
|
|
3197
|
+
$search: { type: "string", description: "OData $search query." }
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3141
3200
|
}
|
|
3142
3201
|
]
|
|
3143
3202
|
},
|
|
3144
3203
|
async executeRead(inv) {
|
|
3145
|
-
if (inv.capabilityName !== "list_availability") {
|
|
3146
|
-
throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
|
|
3147
|
-
}
|
|
3148
|
-
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3149
|
-
const { timeMin, timeMax } = inv.args;
|
|
3150
3204
|
const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3205
|
+
if (inv.capabilityName === "list_availability") {
|
|
3206
|
+
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3207
|
+
const { timeMin, timeMax } = inv.args;
|
|
3208
|
+
const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin, timeMax });
|
|
3209
|
+
return {
|
|
3210
|
+
data: { busy },
|
|
3211
|
+
fetchedAt: Date.now()
|
|
3212
|
+
};
|
|
3213
|
+
}
|
|
3214
|
+
if (inv.capabilityName === "list_events") {
|
|
3215
|
+
const {
|
|
3216
|
+
calendarId,
|
|
3217
|
+
$top,
|
|
3218
|
+
$skip,
|
|
3219
|
+
$filter,
|
|
3220
|
+
$select,
|
|
3221
|
+
$orderby,
|
|
3222
|
+
$search
|
|
3223
|
+
} = inv.args;
|
|
3224
|
+
const base = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
|
|
3225
|
+
const qs = new URLSearchParams();
|
|
3226
|
+
if ($top !== void 0) qs.set("$top", String($top));
|
|
3227
|
+
if ($skip !== void 0) qs.set("$skip", String($skip));
|
|
3228
|
+
if ($filter) qs.set("$filter", $filter);
|
|
3229
|
+
if ($select) qs.set("$select", $select);
|
|
3230
|
+
if ($orderby) qs.set("$orderby", $orderby);
|
|
3231
|
+
if ($search) qs.set("$search", $search);
|
|
3232
|
+
const query = qs.toString();
|
|
3233
|
+
const url = query ? `${base}?${query}` : base;
|
|
3234
|
+
const res = await fetch(url, {
|
|
3235
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
3236
|
+
signal: AbortSignal.timeout(15e3)
|
|
3237
|
+
});
|
|
3238
|
+
if (res.status === 401 || res.status === 403) {
|
|
3239
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3240
|
+
}
|
|
3241
|
+
if (!res.ok) {
|
|
3242
|
+
const text = await res.text().catch(() => "");
|
|
3243
|
+
throw new Error(`microsoft-calendar list_events ${res.status}: ${text.slice(0, 200)}`);
|
|
3244
|
+
}
|
|
3245
|
+
const json = await res.json();
|
|
3246
|
+
return {
|
|
3247
|
+
data: { events: json.value ?? [], nextLink: json["@odata.nextLink"] },
|
|
3248
|
+
fetchedAt: Date.now()
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3251
|
+
throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
|
|
3156
3252
|
},
|
|
3157
3253
|
async executeMutation(inv) {
|
|
3158
|
-
if (inv.capabilityName !== "book_slot") {
|
|
3159
|
-
throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
|
|
3160
|
-
}
|
|
3161
|
-
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3162
|
-
const { start, end, summary, description, attendees } = inv.args;
|
|
3163
3254
|
const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
const
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3255
|
+
if (inv.capabilityName === "book_slot") {
|
|
3256
|
+
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3257
|
+
const {
|
|
3258
|
+
start,
|
|
3259
|
+
end,
|
|
3260
|
+
summary,
|
|
3261
|
+
description,
|
|
3262
|
+
attendees,
|
|
3263
|
+
calendarId,
|
|
3264
|
+
location,
|
|
3265
|
+
recurrence,
|
|
3266
|
+
isOnlineMeeting,
|
|
3267
|
+
onlineMeetingProvider,
|
|
3268
|
+
reminderMinutesBeforeStart,
|
|
3269
|
+
isAllDay,
|
|
3270
|
+
categories,
|
|
3271
|
+
importance
|
|
3272
|
+
} = inv.args;
|
|
3273
|
+
const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin: start, timeMax: end });
|
|
3274
|
+
if (busy.length > 0) {
|
|
3275
|
+
const startMs = Date.parse(start);
|
|
3276
|
+
const endMs = Date.parse(end);
|
|
3277
|
+
const durMs = endMs - startMs;
|
|
3278
|
+
const alternatives = await findNextFreeSlots2({
|
|
3279
|
+
accessToken,
|
|
3280
|
+
userPrincipal,
|
|
3281
|
+
searchFromMs: endMs,
|
|
3282
|
+
durationMs: durMs,
|
|
3283
|
+
wanted: 3
|
|
3284
|
+
});
|
|
3285
|
+
throw new ResourceContention(
|
|
3286
|
+
`requested slot ${start}\u2013${end} is no longer free`,
|
|
3287
|
+
alternatives,
|
|
3288
|
+
{ busy }
|
|
3289
|
+
);
|
|
3290
|
+
}
|
|
3291
|
+
const event = {
|
|
3292
|
+
subject: summary,
|
|
3293
|
+
body: description ? { contentType: "text", content: description } : void 0,
|
|
3294
|
+
start: { dateTime: start, timeZone: "UTC" },
|
|
3295
|
+
end: { dateTime: end, timeZone: "UTC" },
|
|
3296
|
+
attendees: attendees?.map((email) => ({
|
|
3297
|
+
emailAddress: { address: email },
|
|
3298
|
+
type: "required"
|
|
3299
|
+
}))
|
|
3300
|
+
};
|
|
3301
|
+
if (location !== void 0) event.location = location;
|
|
3302
|
+
if (recurrence !== void 0) event.recurrence = recurrence;
|
|
3303
|
+
if (isOnlineMeeting !== void 0) event.isOnlineMeeting = isOnlineMeeting;
|
|
3304
|
+
if (onlineMeetingProvider !== void 0) event.onlineMeetingProvider = onlineMeetingProvider;
|
|
3305
|
+
if (reminderMinutesBeforeStart !== void 0) event.reminderMinutesBeforeStart = reminderMinutesBeforeStart;
|
|
3306
|
+
if (isAllDay !== void 0) event.isAllDay = isAllDay;
|
|
3307
|
+
if (categories !== void 0) event.categories = categories;
|
|
3308
|
+
if (importance !== void 0) event.importance = importance;
|
|
3309
|
+
const url = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
|
|
3310
|
+
const res = await fetch(url, {
|
|
3311
|
+
method: "POST",
|
|
3312
|
+
headers: {
|
|
3313
|
+
authorization: `Bearer ${accessToken}`,
|
|
3314
|
+
"content-type": "application/json"
|
|
3315
|
+
},
|
|
3316
|
+
body: JSON.stringify(event),
|
|
3317
|
+
signal: AbortSignal.timeout(15e3)
|
|
3175
3318
|
});
|
|
3176
|
-
|
|
3177
|
-
`
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
},
|
|
3198
|
-
body: JSON.stringify(event),
|
|
3199
|
-
signal: AbortSignal.timeout(15e3)
|
|
3200
|
-
});
|
|
3201
|
-
if (res.status === 401 || res.status === 403) {
|
|
3202
|
-
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3319
|
+
if (res.status === 401 || res.status === 403) {
|
|
3320
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3321
|
+
}
|
|
3322
|
+
if (res.status === 412 || res.status === 409) {
|
|
3323
|
+
throw new ResourceContention(
|
|
3324
|
+
`Microsoft Graph reported conflict on book_slot (${res.status})`,
|
|
3325
|
+
[]
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
if (!res.ok) {
|
|
3329
|
+
const text = await res.text().catch(() => "");
|
|
3330
|
+
throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
|
|
3331
|
+
}
|
|
3332
|
+
const created = await res.json();
|
|
3333
|
+
return {
|
|
3334
|
+
status: "committed",
|
|
3335
|
+
data: { eventId: created.id, webLink: created.webLink },
|
|
3336
|
+
etagAfter: created["@odata.etag"],
|
|
3337
|
+
committedAt: Date.now(),
|
|
3338
|
+
idempotentReplay: false
|
|
3339
|
+
};
|
|
3203
3340
|
}
|
|
3204
|
-
if (
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3341
|
+
if (inv.capabilityName === "delete_event") {
|
|
3342
|
+
const { eventId } = inv.args;
|
|
3343
|
+
const headers = { authorization: `Bearer ${accessToken}` };
|
|
3344
|
+
if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
|
|
3345
|
+
const res = await fetch(
|
|
3346
|
+
`https://graph.microsoft.com/v1.0/me/events/${encodeURIComponent(eventId)}`,
|
|
3347
|
+
{
|
|
3348
|
+
method: "DELETE",
|
|
3349
|
+
headers,
|
|
3350
|
+
signal: AbortSignal.timeout(15e3)
|
|
3351
|
+
}
|
|
3208
3352
|
);
|
|
3353
|
+
if (res.status === 401 || res.status === 403) {
|
|
3354
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3355
|
+
}
|
|
3356
|
+
if (res.status === 412 || res.status === 409) {
|
|
3357
|
+
throw new ResourceContention(
|
|
3358
|
+
`Microsoft Graph reported conflict on delete_event (${res.status})`,
|
|
3359
|
+
[]
|
|
3360
|
+
);
|
|
3361
|
+
}
|
|
3362
|
+
if (res.status === 404) {
|
|
3363
|
+
return {
|
|
3364
|
+
status: "committed",
|
|
3365
|
+
data: { eventId, deleted: true, alreadyMissing: true },
|
|
3366
|
+
committedAt: Date.now(),
|
|
3367
|
+
idempotentReplay: true
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
if (!res.ok) {
|
|
3371
|
+
const text = await res.text().catch(() => "");
|
|
3372
|
+
throw new Error(`microsoft-calendar delete_event ${res.status}: ${text.slice(0, 200)}`);
|
|
3373
|
+
}
|
|
3374
|
+
return {
|
|
3375
|
+
status: "committed",
|
|
3376
|
+
data: { eventId, deleted: true },
|
|
3377
|
+
committedAt: Date.now(),
|
|
3378
|
+
idempotentReplay: false
|
|
3379
|
+
};
|
|
3209
3380
|
}
|
|
3210
|
-
|
|
3211
|
-
const text = await res.text().catch(() => "");
|
|
3212
|
-
throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
|
|
3213
|
-
}
|
|
3214
|
-
const created = await res.json();
|
|
3215
|
-
return {
|
|
3216
|
-
status: "committed",
|
|
3217
|
-
data: { eventId: created.id, webLink: created.webLink },
|
|
3218
|
-
etagAfter: created["@odata.etag"],
|
|
3219
|
-
committedAt: Date.now(),
|
|
3220
|
-
idempotentReplay: false
|
|
3221
|
-
};
|
|
3381
|
+
throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
|
|
3222
3382
|
},
|
|
3223
3383
|
async exchangeOAuth(input) {
|
|
3224
3384
|
if (!clientId || !clientSecret) {
|
|
@@ -4438,518 +4598,6 @@ async function uploadFile2(inv, accessToken, timeoutMs) {
|
|
|
4438
4598
|
};
|
|
4439
4599
|
}
|
|
4440
4600
|
|
|
4441
|
-
// src/connectors/adapters/notion-database.ts
|
|
4442
|
-
var AUTH_URL8 = "https://api.notion.com/v1/oauth/authorize";
|
|
4443
|
-
var TOKEN_URL8 = "https://api.notion.com/v1/oauth/token";
|
|
4444
|
-
var API5 = "https://api.notion.com/v1";
|
|
4445
|
-
var NOTION_VERSION = "2022-06-28";
|
|
4446
|
-
function notionDatabase(opts) {
|
|
4447
|
-
const { clientId, clientSecret } = opts;
|
|
4448
|
-
const adapter = {
|
|
4449
|
-
manifest: {
|
|
4450
|
-
kind: "notion-database",
|
|
4451
|
-
displayName: "Notion (database)",
|
|
4452
|
-
description: "Query a Notion database, create new pages, and update existing ones with optimistic concurrency via last_edited_time.",
|
|
4453
|
-
auth: {
|
|
4454
|
-
kind: "oauth2",
|
|
4455
|
-
authorizationUrl: AUTH_URL8,
|
|
4456
|
-
tokenUrl: TOKEN_URL8,
|
|
4457
|
-
// Notion does not use OAuth scopes — the workspace owner picks
|
|
4458
|
-
// which pages/databases the integration sees during install. We
|
|
4459
|
-
// declare an empty scope list so the consent screen renders cleanly.
|
|
4460
|
-
scopes: [],
|
|
4461
|
-
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
4462
|
-
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
4463
|
-
extraAuthParams: { owner: "user" }
|
|
4464
|
-
},
|
|
4465
|
-
category: "doc",
|
|
4466
|
-
defaultConsistencyModel: "authoritative",
|
|
4467
|
-
capabilities: [
|
|
4468
|
-
{
|
|
4469
|
-
name: "query_database",
|
|
4470
|
-
class: "read",
|
|
4471
|
-
description: "Query the connected Notion database with an optional filter object (Notion query DSL).",
|
|
4472
|
-
parameters: {
|
|
4473
|
-
type: "object",
|
|
4474
|
-
properties: {
|
|
4475
|
-
filter: { type: "object", description: "Notion API filter object \u2014 passed through verbatim." },
|
|
4476
|
-
pageSize: { type: "integer", minimum: 1, maximum: 100, default: 50 },
|
|
4477
|
-
startCursor: { type: "string" }
|
|
4478
|
-
}
|
|
4479
|
-
}
|
|
4480
|
-
},
|
|
4481
|
-
{
|
|
4482
|
-
name: "create_page",
|
|
4483
|
-
class: "mutation",
|
|
4484
|
-
description: "Create a new page inside the connected database.",
|
|
4485
|
-
cas: "native-idempotency",
|
|
4486
|
-
externalEffect: true,
|
|
4487
|
-
parameters: {
|
|
4488
|
-
type: "object",
|
|
4489
|
-
properties: {
|
|
4490
|
-
properties: {
|
|
4491
|
-
type: "object",
|
|
4492
|
-
description: "Notion property map keyed by property name."
|
|
4493
|
-
}
|
|
4494
|
-
},
|
|
4495
|
-
required: ["properties"]
|
|
4496
|
-
}
|
|
4497
|
-
},
|
|
4498
|
-
{
|
|
4499
|
-
name: "update_page",
|
|
4500
|
-
class: "mutation",
|
|
4501
|
-
description: "Update properties on an existing page. If `expectedLastEditedTime` is supplied and stale, the update is rejected with conflict.",
|
|
4502
|
-
cas: "etag-if-match",
|
|
4503
|
-
externalEffect: true,
|
|
4504
|
-
parameters: {
|
|
4505
|
-
type: "object",
|
|
4506
|
-
properties: {
|
|
4507
|
-
pageId: { type: "string" },
|
|
4508
|
-
properties: { type: "object" },
|
|
4509
|
-
expectedLastEditedTime: {
|
|
4510
|
-
type: "string",
|
|
4511
|
-
description: "RFC3339 timestamp the agent observed on its last read. Drift triggers ResourceContention."
|
|
4512
|
-
}
|
|
4513
|
-
},
|
|
4514
|
-
required: ["pageId", "properties"]
|
|
4515
|
-
}
|
|
4516
|
-
},
|
|
4517
|
-
{
|
|
4518
|
-
name: "pages.archive",
|
|
4519
|
-
class: "mutation",
|
|
4520
|
-
description: "Archive (soft-delete) a Notion page. Restorable via update_page with archived:false.",
|
|
4521
|
-
cas: "native-idempotency",
|
|
4522
|
-
externalEffect: true,
|
|
4523
|
-
parameters: {
|
|
4524
|
-
type: "object",
|
|
4525
|
-
properties: { pageId: { type: "string" } },
|
|
4526
|
-
required: ["pageId"]
|
|
4527
|
-
}
|
|
4528
|
-
},
|
|
4529
|
-
{
|
|
4530
|
-
name: "databases.create",
|
|
4531
|
-
class: "mutation",
|
|
4532
|
-
description: "Create a new Notion database underneath a parent page.",
|
|
4533
|
-
cas: "native-idempotency",
|
|
4534
|
-
externalEffect: true,
|
|
4535
|
-
parameters: {
|
|
4536
|
-
type: "object",
|
|
4537
|
-
properties: {
|
|
4538
|
-
parentPageId: { type: "string", description: "Parent page id under which to create the database." },
|
|
4539
|
-
title: {
|
|
4540
|
-
type: "array",
|
|
4541
|
-
description: "Notion rich_text array used as the database title."
|
|
4542
|
-
},
|
|
4543
|
-
properties: {
|
|
4544
|
-
type: "object",
|
|
4545
|
-
description: "Schema map \u2014 property name \u2192 Notion property schema."
|
|
4546
|
-
}
|
|
4547
|
-
},
|
|
4548
|
-
required: ["parentPageId", "title", "properties"]
|
|
4549
|
-
}
|
|
4550
|
-
},
|
|
4551
|
-
{
|
|
4552
|
-
name: "databases.update",
|
|
4553
|
-
class: "mutation",
|
|
4554
|
-
description: "Update a database title and/or schema.",
|
|
4555
|
-
cas: "native-idempotency",
|
|
4556
|
-
externalEffect: true,
|
|
4557
|
-
parameters: {
|
|
4558
|
-
type: "object",
|
|
4559
|
-
properties: {
|
|
4560
|
-
databaseId: { type: "string" },
|
|
4561
|
-
title: { type: "array", description: "Optional new rich_text title." },
|
|
4562
|
-
properties: { type: "object", description: "Optional partial schema update." }
|
|
4563
|
-
},
|
|
4564
|
-
required: ["databaseId"]
|
|
4565
|
-
}
|
|
4566
|
-
},
|
|
4567
|
-
{
|
|
4568
|
-
name: "blocks.append",
|
|
4569
|
-
class: "mutation",
|
|
4570
|
-
description: "Append child blocks to a page or block.",
|
|
4571
|
-
cas: "native-idempotency",
|
|
4572
|
-
externalEffect: true,
|
|
4573
|
-
parameters: {
|
|
4574
|
-
type: "object",
|
|
4575
|
-
properties: {
|
|
4576
|
-
blockId: { type: "string", description: "Parent page or block id." },
|
|
4577
|
-
children: { type: "array", description: "Block descriptor array per Notion schema." }
|
|
4578
|
-
},
|
|
4579
|
-
required: ["blockId", "children"]
|
|
4580
|
-
}
|
|
4581
|
-
}
|
|
4582
|
-
]
|
|
4583
|
-
},
|
|
4584
|
-
async executeRead(inv) {
|
|
4585
|
-
if (inv.capabilityName !== "query_database") {
|
|
4586
|
-
throw new Error(`notion-database: unknown read capability ${inv.capabilityName}`);
|
|
4587
|
-
}
|
|
4588
|
-
const accessToken = readToken(inv.source.credentials);
|
|
4589
|
-
const databaseId = readMetaString3(inv.source.metadata, "databaseId");
|
|
4590
|
-
const { filter, pageSize, startCursor } = inv.args;
|
|
4591
|
-
const body = {
|
|
4592
|
-
page_size: Math.min(Math.max(1, pageSize ?? 50), 100)
|
|
4593
|
-
};
|
|
4594
|
-
if (filter) body.filter = filter;
|
|
4595
|
-
if (startCursor) body.start_cursor = startCursor;
|
|
4596
|
-
const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}/query`, {
|
|
4597
|
-
method: "POST",
|
|
4598
|
-
headers: notionHeaders(accessToken),
|
|
4599
|
-
body: JSON.stringify(body),
|
|
4600
|
-
signal: AbortSignal.timeout(1e4)
|
|
4601
|
-
});
|
|
4602
|
-
if (res.status === 401) {
|
|
4603
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4604
|
-
}
|
|
4605
|
-
if (!res.ok) {
|
|
4606
|
-
const text = await res.text().catch(() => "");
|
|
4607
|
-
throw new Error(`notion-database query_database ${res.status}: ${text.slice(0, 200)}`);
|
|
4608
|
-
}
|
|
4609
|
-
const json = await res.json();
|
|
4610
|
-
return {
|
|
4611
|
-
data: {
|
|
4612
|
-
results: json.results ?? [],
|
|
4613
|
-
hasMore: json.has_more ?? false,
|
|
4614
|
-
nextCursor: json.next_cursor ?? null
|
|
4615
|
-
},
|
|
4616
|
-
fetchedAt: Date.now()
|
|
4617
|
-
};
|
|
4618
|
-
},
|
|
4619
|
-
async executeMutation(inv) {
|
|
4620
|
-
const accessToken = readToken(inv.source.credentials);
|
|
4621
|
-
if (inv.capabilityName === "create_page") return createPage(inv, accessToken);
|
|
4622
|
-
if (inv.capabilityName === "update_page") return updatePage(inv, accessToken);
|
|
4623
|
-
if (inv.capabilityName === "pages.archive") return archivePage(inv, accessToken);
|
|
4624
|
-
if (inv.capabilityName === "databases.create") return createDatabase(inv, accessToken);
|
|
4625
|
-
if (inv.capabilityName === "databases.update") return updateDatabase(inv, accessToken);
|
|
4626
|
-
if (inv.capabilityName === "blocks.append") return appendBlocks(inv, accessToken);
|
|
4627
|
-
throw new Error(`notion-database: unknown mutation capability ${inv.capabilityName}`);
|
|
4628
|
-
},
|
|
4629
|
-
async exchangeOAuth(input) {
|
|
4630
|
-
if (!clientId || !clientSecret) {
|
|
4631
|
-
throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
|
|
4632
|
-
}
|
|
4633
|
-
const body = new URLSearchParams({
|
|
4634
|
-
grant_type: "authorization_code",
|
|
4635
|
-
code: input.code,
|
|
4636
|
-
redirect_uri: input.redirectUri,
|
|
4637
|
-
code_verifier: input.codeVerifier
|
|
4638
|
-
});
|
|
4639
|
-
const res = await fetch(TOKEN_URL8, {
|
|
4640
|
-
method: "POST",
|
|
4641
|
-
headers: {
|
|
4642
|
-
authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
|
|
4643
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
4644
|
-
accept: "application/json",
|
|
4645
|
-
"Notion-Version": NOTION_VERSION
|
|
4646
|
-
},
|
|
4647
|
-
body
|
|
4648
|
-
});
|
|
4649
|
-
if (!res.ok) {
|
|
4650
|
-
const text = await res.text().catch(() => "");
|
|
4651
|
-
throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
|
|
4652
|
-
}
|
|
4653
|
-
const json = await res.json();
|
|
4654
|
-
return {
|
|
4655
|
-
credentials: {
|
|
4656
|
-
kind: "oauth2",
|
|
4657
|
-
accessToken: json.access_token,
|
|
4658
|
-
refreshToken: json.refresh_token
|
|
4659
|
-
},
|
|
4660
|
-
scopes: [],
|
|
4661
|
-
metadata: {
|
|
4662
|
-
botId: json.bot_id,
|
|
4663
|
-
workspaceId: json.workspace_id,
|
|
4664
|
-
workspaceName: json.workspace_name,
|
|
4665
|
-
// Operator picks the database in a follow-up step; default empty.
|
|
4666
|
-
databaseId: ""
|
|
4667
|
-
}
|
|
4668
|
-
};
|
|
4669
|
-
},
|
|
4670
|
-
async refreshToken(creds) {
|
|
4671
|
-
if (creds.kind !== "oauth2" || !creds.refreshToken) {
|
|
4672
|
-
if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
|
|
4673
|
-
return creds;
|
|
4674
|
-
}
|
|
4675
|
-
throw new Error("notion-database.refreshToken: missing refresh token");
|
|
4676
|
-
}
|
|
4677
|
-
const refreshed = await refreshAccessToken({
|
|
4678
|
-
tokenUrl: TOKEN_URL8,
|
|
4679
|
-
clientId,
|
|
4680
|
-
clientSecret,
|
|
4681
|
-
refreshToken: creds.refreshToken
|
|
4682
|
-
});
|
|
4683
|
-
return {
|
|
4684
|
-
kind: "oauth2",
|
|
4685
|
-
accessToken: refreshed.accessToken,
|
|
4686
|
-
refreshToken: refreshed.refreshToken ?? creds.refreshToken,
|
|
4687
|
-
expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
|
|
4688
|
-
};
|
|
4689
|
-
},
|
|
4690
|
-
async test(source) {
|
|
4691
|
-
try {
|
|
4692
|
-
const accessToken = readToken(source.credentials);
|
|
4693
|
-
const res = await fetch(`${API5}/users/me`, {
|
|
4694
|
-
headers: notionHeaders(accessToken),
|
|
4695
|
-
signal: AbortSignal.timeout(8e3)
|
|
4696
|
-
});
|
|
4697
|
-
if (res.status === 401) return { ok: false, reason: "Notion rejected token (401) \u2014 reconnect required" };
|
|
4698
|
-
if (!res.ok) return { ok: false, reason: `Notion returned ${res.status}` };
|
|
4699
|
-
return { ok: true };
|
|
4700
|
-
} catch (err) {
|
|
4701
|
-
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
4702
|
-
}
|
|
4703
|
-
}
|
|
4704
|
-
};
|
|
4705
|
-
return adapter;
|
|
4706
|
-
}
|
|
4707
|
-
async function createPage(inv, accessToken) {
|
|
4708
|
-
const databaseId = readMetaString3(inv.source.metadata, "databaseId");
|
|
4709
|
-
const { properties } = inv.args;
|
|
4710
|
-
const res = await fetch(`${API5}/pages`, {
|
|
4711
|
-
method: "POST",
|
|
4712
|
-
headers: {
|
|
4713
|
-
...notionHeaders(accessToken),
|
|
4714
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4715
|
-
},
|
|
4716
|
-
body: JSON.stringify({
|
|
4717
|
-
parent: { database_id: databaseId },
|
|
4718
|
-
properties
|
|
4719
|
-
}),
|
|
4720
|
-
signal: AbortSignal.timeout(15e3)
|
|
4721
|
-
});
|
|
4722
|
-
if (res.status === 401) {
|
|
4723
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4724
|
-
}
|
|
4725
|
-
if (res.status === 409) {
|
|
4726
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4727
|
-
}
|
|
4728
|
-
if (!res.ok) {
|
|
4729
|
-
const text = await res.text().catch(() => "");
|
|
4730
|
-
throw new Error(`notion-database create_page ${res.status}: ${text.slice(0, 200)}`);
|
|
4731
|
-
}
|
|
4732
|
-
const created = await res.json();
|
|
4733
|
-
return {
|
|
4734
|
-
status: "committed",
|
|
4735
|
-
data: { pageId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
|
|
4736
|
-
etagAfter: created.last_edited_time,
|
|
4737
|
-
committedAt: Date.now(),
|
|
4738
|
-
idempotentReplay: false
|
|
4739
|
-
};
|
|
4740
|
-
}
|
|
4741
|
-
async function updatePage(inv, accessToken) {
|
|
4742
|
-
const { pageId, properties, expectedLastEditedTime } = inv.args;
|
|
4743
|
-
if (expectedLastEditedTime) {
|
|
4744
|
-
const headRes = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4745
|
-
headers: notionHeaders(accessToken),
|
|
4746
|
-
signal: AbortSignal.timeout(1e4)
|
|
4747
|
-
});
|
|
4748
|
-
if (headRes.status === 401) {
|
|
4749
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4750
|
-
}
|
|
4751
|
-
if (!headRes.ok) {
|
|
4752
|
-
const text = await headRes.text().catch(() => "");
|
|
4753
|
-
throw new Error(`notion-database update_page (preflight) ${headRes.status}: ${text.slice(0, 200)}`);
|
|
4754
|
-
}
|
|
4755
|
-
const page = await headRes.json();
|
|
4756
|
-
if (page.last_edited_time && page.last_edited_time !== expectedLastEditedTime) {
|
|
4757
|
-
throw new ResourceContention(
|
|
4758
|
-
`Notion page ${pageId} was modified since the agent last read it`,
|
|
4759
|
-
[],
|
|
4760
|
-
{ last_edited_time: page.last_edited_time, properties: page.properties }
|
|
4761
|
-
);
|
|
4762
|
-
}
|
|
4763
|
-
}
|
|
4764
|
-
const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4765
|
-
method: "PATCH",
|
|
4766
|
-
headers: notionHeaders(accessToken),
|
|
4767
|
-
body: JSON.stringify({ properties }),
|
|
4768
|
-
signal: AbortSignal.timeout(15e3)
|
|
4769
|
-
});
|
|
4770
|
-
if (res.status === 401) {
|
|
4771
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4772
|
-
}
|
|
4773
|
-
if (res.status === 409 || res.status === 412) {
|
|
4774
|
-
throw new ResourceContention(`Notion update_page conflict (${res.status})`);
|
|
4775
|
-
}
|
|
4776
|
-
if (!res.ok) {
|
|
4777
|
-
const text = await res.text().catch(() => "");
|
|
4778
|
-
throw new Error(`notion-database update_page ${res.status}: ${text.slice(0, 200)}`);
|
|
4779
|
-
}
|
|
4780
|
-
const updated = await res.json();
|
|
4781
|
-
return {
|
|
4782
|
-
status: "committed",
|
|
4783
|
-
data: { pageId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
|
|
4784
|
-
etagAfter: updated.last_edited_time,
|
|
4785
|
-
committedAt: Date.now(),
|
|
4786
|
-
idempotentReplay: false
|
|
4787
|
-
};
|
|
4788
|
-
}
|
|
4789
|
-
async function archivePage(inv, accessToken) {
|
|
4790
|
-
const { pageId } = inv.args;
|
|
4791
|
-
if (typeof pageId !== "string" || pageId.length === 0) {
|
|
4792
|
-
throw new Error("notion-database pages.archive: pageId is required");
|
|
4793
|
-
}
|
|
4794
|
-
const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4795
|
-
method: "PATCH",
|
|
4796
|
-
headers: {
|
|
4797
|
-
...notionHeaders(accessToken),
|
|
4798
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4799
|
-
},
|
|
4800
|
-
body: JSON.stringify({ archived: true }),
|
|
4801
|
-
signal: AbortSignal.timeout(15e3)
|
|
4802
|
-
});
|
|
4803
|
-
if (res.status === 401) {
|
|
4804
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4805
|
-
}
|
|
4806
|
-
if (res.status === 409) {
|
|
4807
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4808
|
-
}
|
|
4809
|
-
if (!res.ok) {
|
|
4810
|
-
const text = await res.text().catch(() => "");
|
|
4811
|
-
throw new Error(`notion-database pages.archive ${res.status}: ${text.slice(0, 200)}`);
|
|
4812
|
-
}
|
|
4813
|
-
const archived = await res.json();
|
|
4814
|
-
return {
|
|
4815
|
-
status: "committed",
|
|
4816
|
-
data: { pageId: archived.id, archived: archived.archived ?? true, lastEditedTime: archived.last_edited_time },
|
|
4817
|
-
etagAfter: archived.last_edited_time,
|
|
4818
|
-
committedAt: Date.now(),
|
|
4819
|
-
idempotentReplay: false
|
|
4820
|
-
};
|
|
4821
|
-
}
|
|
4822
|
-
async function createDatabase(inv, accessToken) {
|
|
4823
|
-
const { parentPageId, title, properties } = inv.args;
|
|
4824
|
-
if (typeof parentPageId !== "string" || parentPageId.length === 0) {
|
|
4825
|
-
throw new Error("notion-database databases.create: parentPageId is required");
|
|
4826
|
-
}
|
|
4827
|
-
if (!title) throw new Error("notion-database databases.create: title is required");
|
|
4828
|
-
if (!properties) throw new Error("notion-database databases.create: properties is required");
|
|
4829
|
-
const res = await fetch(`${API5}/databases`, {
|
|
4830
|
-
method: "POST",
|
|
4831
|
-
headers: {
|
|
4832
|
-
...notionHeaders(accessToken),
|
|
4833
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4834
|
-
},
|
|
4835
|
-
body: JSON.stringify({
|
|
4836
|
-
parent: { type: "page_id", page_id: parentPageId },
|
|
4837
|
-
title,
|
|
4838
|
-
properties
|
|
4839
|
-
}),
|
|
4840
|
-
signal: AbortSignal.timeout(15e3)
|
|
4841
|
-
});
|
|
4842
|
-
if (res.status === 401) {
|
|
4843
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4844
|
-
}
|
|
4845
|
-
if (res.status === 409) {
|
|
4846
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4847
|
-
}
|
|
4848
|
-
if (!res.ok) {
|
|
4849
|
-
const text = await res.text().catch(() => "");
|
|
4850
|
-
throw new Error(`notion-database databases.create ${res.status}: ${text.slice(0, 200)}`);
|
|
4851
|
-
}
|
|
4852
|
-
const created = await res.json();
|
|
4853
|
-
return {
|
|
4854
|
-
status: "committed",
|
|
4855
|
-
data: { databaseId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
|
|
4856
|
-
etagAfter: created.last_edited_time,
|
|
4857
|
-
committedAt: Date.now(),
|
|
4858
|
-
idempotentReplay: false
|
|
4859
|
-
};
|
|
4860
|
-
}
|
|
4861
|
-
async function updateDatabase(inv, accessToken) {
|
|
4862
|
-
const { databaseId, title, properties } = inv.args;
|
|
4863
|
-
if (typeof databaseId !== "string" || databaseId.length === 0) {
|
|
4864
|
-
throw new Error("notion-database databases.update: databaseId is required");
|
|
4865
|
-
}
|
|
4866
|
-
const body = {};
|
|
4867
|
-
if (title !== void 0) body.title = title;
|
|
4868
|
-
if (properties !== void 0) body.properties = properties;
|
|
4869
|
-
const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}`, {
|
|
4870
|
-
method: "PATCH",
|
|
4871
|
-
headers: {
|
|
4872
|
-
...notionHeaders(accessToken),
|
|
4873
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4874
|
-
},
|
|
4875
|
-
body: JSON.stringify(body),
|
|
4876
|
-
signal: AbortSignal.timeout(15e3)
|
|
4877
|
-
});
|
|
4878
|
-
if (res.status === 401) {
|
|
4879
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4880
|
-
}
|
|
4881
|
-
if (res.status === 409) {
|
|
4882
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4883
|
-
}
|
|
4884
|
-
if (!res.ok) {
|
|
4885
|
-
const text = await res.text().catch(() => "");
|
|
4886
|
-
throw new Error(`notion-database databases.update ${res.status}: ${text.slice(0, 200)}`);
|
|
4887
|
-
}
|
|
4888
|
-
const updated = await res.json();
|
|
4889
|
-
return {
|
|
4890
|
-
status: "committed",
|
|
4891
|
-
data: { databaseId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
|
|
4892
|
-
etagAfter: updated.last_edited_time,
|
|
4893
|
-
committedAt: Date.now(),
|
|
4894
|
-
idempotentReplay: false
|
|
4895
|
-
};
|
|
4896
|
-
}
|
|
4897
|
-
async function appendBlocks(inv, accessToken) {
|
|
4898
|
-
const { blockId, children } = inv.args;
|
|
4899
|
-
if (typeof blockId !== "string" || blockId.length === 0) {
|
|
4900
|
-
throw new Error("notion-database blocks.append: blockId is required");
|
|
4901
|
-
}
|
|
4902
|
-
if (!Array.isArray(children)) {
|
|
4903
|
-
throw new Error("notion-database blocks.append: children must be an array");
|
|
4904
|
-
}
|
|
4905
|
-
const res = await fetch(`${API5}/blocks/${encodeURIComponent(blockId)}/children`, {
|
|
4906
|
-
method: "PATCH",
|
|
4907
|
-
headers: {
|
|
4908
|
-
...notionHeaders(accessToken),
|
|
4909
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4910
|
-
},
|
|
4911
|
-
body: JSON.stringify({ children }),
|
|
4912
|
-
signal: AbortSignal.timeout(15e3)
|
|
4913
|
-
});
|
|
4914
|
-
if (res.status === 401) {
|
|
4915
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4916
|
-
}
|
|
4917
|
-
if (res.status === 409) {
|
|
4918
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4919
|
-
}
|
|
4920
|
-
if (!res.ok) {
|
|
4921
|
-
const text = await res.text().catch(() => "");
|
|
4922
|
-
throw new Error(`notion-database blocks.append ${res.status}: ${text.slice(0, 200)}`);
|
|
4923
|
-
}
|
|
4924
|
-
const json = await res.json();
|
|
4925
|
-
return {
|
|
4926
|
-
status: "committed",
|
|
4927
|
-
data: { results: json.results ?? [] },
|
|
4928
|
-
committedAt: Date.now(),
|
|
4929
|
-
idempotentReplay: false
|
|
4930
|
-
};
|
|
4931
|
-
}
|
|
4932
|
-
function notionHeaders(accessToken) {
|
|
4933
|
-
return {
|
|
4934
|
-
authorization: `Bearer ${accessToken}`,
|
|
4935
|
-
"Notion-Version": NOTION_VERSION,
|
|
4936
|
-
"content-type": "application/json"
|
|
4937
|
-
};
|
|
4938
|
-
}
|
|
4939
|
-
function readToken(creds) {
|
|
4940
|
-
if (creds.kind !== "oauth2" || typeof creds.accessToken !== "string") {
|
|
4941
|
-
throw new Error("notion-database: expected oauth2 credentials");
|
|
4942
|
-
}
|
|
4943
|
-
return creds.accessToken;
|
|
4944
|
-
}
|
|
4945
|
-
function readMetaString3(meta, key) {
|
|
4946
|
-
const v = meta[key];
|
|
4947
|
-
if (typeof v !== "string" || v.length === 0) {
|
|
4948
|
-
throw new Error(`notion-database DataSource.metadata.${key} is missing`);
|
|
4949
|
-
}
|
|
4950
|
-
return v;
|
|
4951
|
-
}
|
|
4952
|
-
|
|
4953
4601
|
// src/connectors/adapters/docuseal.ts
|
|
4954
4602
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
4955
4603
|
var DEFAULT_BASE = "https://api.docuseal.com";
|
|
@@ -5249,7 +4897,7 @@ async function voidSubmission(inv, apiKey, baseUrl, timeoutMs) {
|
|
|
5249
4897
|
}
|
|
5250
4898
|
|
|
5251
4899
|
// src/connectors/adapters/twilio-sms.ts
|
|
5252
|
-
var
|
|
4900
|
+
var API5 = "https://api.twilio.com/2010-04-01";
|
|
5253
4901
|
var LOOKUP_API = "https://lookups.twilio.com/v1";
|
|
5254
4902
|
var twilioSmsConnector = {
|
|
5255
4903
|
manifest: {
|
|
@@ -5406,7 +5054,7 @@ var twilioSmsConnector = {
|
|
|
5406
5054
|
params.set("PageSize", String(Math.min(Math.max(1, limit ?? 20), 100)));
|
|
5407
5055
|
if (to) params.set("To", to);
|
|
5408
5056
|
if (from) params.set("From", from);
|
|
5409
|
-
const url = `${
|
|
5057
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json?${params.toString()}`;
|
|
5410
5058
|
const res = await fetch(url, {
|
|
5411
5059
|
headers: { authorization: basicAuth(auth) },
|
|
5412
5060
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -5427,7 +5075,7 @@ var twilioSmsConnector = {
|
|
|
5427
5075
|
const params = new URLSearchParams();
|
|
5428
5076
|
params.set("PageSize", String(Math.min(Math.max(1, limit ?? 50), 100)));
|
|
5429
5077
|
if (phoneNumber) params.set("PhoneNumber", phoneNumber);
|
|
5430
|
-
const url = `${
|
|
5078
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/IncomingPhoneNumbers.json?${params.toString()}`;
|
|
5431
5079
|
const res = await fetch(url, {
|
|
5432
5080
|
headers: { authorization: basicAuth(auth) },
|
|
5433
5081
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -5449,13 +5097,13 @@ var twilioSmsConnector = {
|
|
|
5449
5097
|
const auth = parseAuth(inv.source.credentials);
|
|
5450
5098
|
if (inv.capabilityName === "send_sms") {
|
|
5451
5099
|
const { to, body, from } = inv.args;
|
|
5452
|
-
const fromNumber = from ??
|
|
5100
|
+
const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5453
5101
|
const formBody = new URLSearchParams({ To: to, From: fromNumber, Body: body });
|
|
5454
5102
|
return await postMessages(inv, auth, formBody, "send_sms");
|
|
5455
5103
|
}
|
|
5456
5104
|
if (inv.capabilityName === "send_mms") {
|
|
5457
5105
|
const { to, body, from, mediaUrl } = inv.args;
|
|
5458
|
-
const fromNumber = from ??
|
|
5106
|
+
const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5459
5107
|
const formBody = new URLSearchParams();
|
|
5460
5108
|
formBody.set("To", to);
|
|
5461
5109
|
formBody.set("From", fromNumber);
|
|
@@ -5467,7 +5115,7 @@ var twilioSmsConnector = {
|
|
|
5467
5115
|
if (inv.capabilityName === "send_whatsapp") {
|
|
5468
5116
|
const { to, body, from } = inv.args;
|
|
5469
5117
|
const ensureWhatsapp = (n) => n.startsWith("whatsapp:") ? n : `whatsapp:${n}`;
|
|
5470
|
-
const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ??
|
|
5118
|
+
const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5471
5119
|
const formBody = new URLSearchParams({
|
|
5472
5120
|
To: ensureWhatsapp(to),
|
|
5473
5121
|
From: ensureWhatsapp(fromRaw),
|
|
@@ -5477,7 +5125,7 @@ var twilioSmsConnector = {
|
|
|
5477
5125
|
}
|
|
5478
5126
|
if (inv.capabilityName === "redact_message") {
|
|
5479
5127
|
const { messageSid } = inv.args;
|
|
5480
|
-
const url = `${
|
|
5128
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages/${encodeURIComponent(messageSid)}.json`;
|
|
5481
5129
|
const formBody = new URLSearchParams({ Body: "" });
|
|
5482
5130
|
const res = await fetch(url, {
|
|
5483
5131
|
method: "POST",
|
|
@@ -5510,7 +5158,7 @@ var twilioSmsConnector = {
|
|
|
5510
5158
|
async test(source) {
|
|
5511
5159
|
try {
|
|
5512
5160
|
const auth = parseAuth(source.credentials);
|
|
5513
|
-
const res = await fetch(`${
|
|
5161
|
+
const res = await fetch(`${API5}/Accounts/${encodeURIComponent(auth.accountSid)}.json`, {
|
|
5514
5162
|
headers: { authorization: basicAuth(auth) },
|
|
5515
5163
|
signal: AbortSignal.timeout(8e3)
|
|
5516
5164
|
});
|
|
@@ -5546,7 +5194,7 @@ function parseAuth(creds) {
|
|
|
5546
5194
|
function basicAuth(auth) {
|
|
5547
5195
|
return `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString("base64")}`;
|
|
5548
5196
|
}
|
|
5549
|
-
function
|
|
5197
|
+
function readMetaString3(meta, key) {
|
|
5550
5198
|
const v = meta[key];
|
|
5551
5199
|
if (typeof v !== "string" || v.length === 0) {
|
|
5552
5200
|
throw new Error(`twilio-sms DataSource.metadata.${key} is missing`);
|
|
@@ -5558,7 +5206,7 @@ function readMetaStringOptional(meta, key) {
|
|
|
5558
5206
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
5559
5207
|
}
|
|
5560
5208
|
async function postMessages(inv, auth, formBody, label) {
|
|
5561
|
-
const url = `${
|
|
5209
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json`;
|
|
5562
5210
|
const res = await fetch(url, {
|
|
5563
5211
|
method: "POST",
|
|
5564
5212
|
headers: {
|
|
@@ -5587,7 +5235,7 @@ async function postMessages(inv, auth, formBody, label) {
|
|
|
5587
5235
|
}
|
|
5588
5236
|
|
|
5589
5237
|
// src/connectors/adapters/phony.ts
|
|
5590
|
-
var
|
|
5238
|
+
var API6 = "https://api.ph0ny.com";
|
|
5591
5239
|
var E164 = /^\+[1-9]\d{7,14}$/;
|
|
5592
5240
|
var phonyConnector = {
|
|
5593
5241
|
manifest: {
|
|
@@ -5857,7 +5505,7 @@ var phonyConnector = {
|
|
|
5857
5505
|
const json = await getJson(
|
|
5858
5506
|
inv,
|
|
5859
5507
|
token,
|
|
5860
|
-
`${
|
|
5508
|
+
`${API6}/v1/agents?${params.toString()}`,
|
|
5861
5509
|
"list_agents"
|
|
5862
5510
|
);
|
|
5863
5511
|
return {
|
|
@@ -5870,7 +5518,7 @@ var phonyConnector = {
|
|
|
5870
5518
|
const json = await getJson(
|
|
5871
5519
|
inv,
|
|
5872
5520
|
token,
|
|
5873
|
-
`${
|
|
5521
|
+
`${API6}/v1/outbound/${encodeURIComponent(id)}`,
|
|
5874
5522
|
"get_call"
|
|
5875
5523
|
);
|
|
5876
5524
|
return { data: { call: json.call ?? null }, fetchedAt: Date.now() };
|
|
@@ -5883,7 +5531,7 @@ var phonyConnector = {
|
|
|
5883
5531
|
const json = await getJson(
|
|
5884
5532
|
inv,
|
|
5885
5533
|
token,
|
|
5886
|
-
`${
|
|
5534
|
+
`${API6}/v1/outbound?${params.toString()}`,
|
|
5887
5535
|
"list_calls"
|
|
5888
5536
|
);
|
|
5889
5537
|
return { data: { calls: json.calls ?? [] }, fetchedAt: Date.now() };
|
|
@@ -5894,7 +5542,7 @@ var phonyConnector = {
|
|
|
5894
5542
|
if (limit !== void 0) payload.limit = limit;
|
|
5895
5543
|
if (threshold !== void 0) payload.threshold = threshold;
|
|
5896
5544
|
if (includeMetadata !== void 0) payload.includeMetadata = includeMetadata;
|
|
5897
|
-
const res = await fetch(`${
|
|
5545
|
+
const res = await fetch(`${API6}/v1/collections/${encodeURIComponent(collectionId)}/search`, {
|
|
5898
5546
|
method: "POST",
|
|
5899
5547
|
headers: {
|
|
5900
5548
|
authorization: `Bearer ${token}`,
|
|
@@ -5935,7 +5583,7 @@ var phonyConnector = {
|
|
|
5935
5583
|
if (args.callerProfile !== void 0) payload.callerProfile = args.callerProfile;
|
|
5936
5584
|
if (args.voiceCloneId !== void 0) payload.voiceCloneId = args.voiceCloneId;
|
|
5937
5585
|
if (args.dryRun !== void 0) payload.dryRun = args.dryRun;
|
|
5938
|
-
const res = await fetch(`${
|
|
5586
|
+
const res = await fetch(`${API6}/v1/outbound/start`, {
|
|
5939
5587
|
method: "POST",
|
|
5940
5588
|
headers: {
|
|
5941
5589
|
authorization: `Bearer ${token}`,
|
|
@@ -5965,7 +5613,7 @@ var phonyConnector = {
|
|
|
5965
5613
|
}
|
|
5966
5614
|
if (inv.capabilityName === "create_agent") {
|
|
5967
5615
|
const payload = pick(inv.args, AGENT_FIELDS);
|
|
5968
|
-
const json = await postJson(inv, token, `${
|
|
5616
|
+
const json = await postJson(inv, token, `${API6}/v1/agents`, payload, "create_agent");
|
|
5969
5617
|
return {
|
|
5970
5618
|
status: "committed",
|
|
5971
5619
|
data: { agent: json },
|
|
@@ -5981,7 +5629,7 @@ var phonyConnector = {
|
|
|
5981
5629
|
const json = await postJson(
|
|
5982
5630
|
inv,
|
|
5983
5631
|
token,
|
|
5984
|
-
`${
|
|
5632
|
+
`${API6}/v1/agents/provision`,
|
|
5985
5633
|
payload,
|
|
5986
5634
|
"provision_agent"
|
|
5987
5635
|
);
|
|
@@ -6001,7 +5649,7 @@ var phonyConnector = {
|
|
|
6001
5649
|
const payload = { name };
|
|
6002
5650
|
if (description !== void 0) payload.description = description;
|
|
6003
5651
|
if (metadata !== void 0) payload.metadata = metadata;
|
|
6004
|
-
const json = await postJson(inv, token, `${
|
|
5652
|
+
const json = await postJson(inv, token, `${API6}/v1/collections`, payload, "kb_create_collection");
|
|
6005
5653
|
return {
|
|
6006
5654
|
status: "committed",
|
|
6007
5655
|
data: { collection: json },
|
|
@@ -6015,7 +5663,7 @@ var phonyConnector = {
|
|
|
6015
5663
|
const json = await postJson(
|
|
6016
5664
|
inv,
|
|
6017
5665
|
token,
|
|
6018
|
-
`${
|
|
5666
|
+
`${API6}/v1/collections/${encodeURIComponent(collectionId)}/ingest`,
|
|
6019
5667
|
payload,
|
|
6020
5668
|
"kb_ingest"
|
|
6021
5669
|
);
|
|
@@ -6035,7 +5683,7 @@ var phonyConnector = {
|
|
|
6035
5683
|
async test(source) {
|
|
6036
5684
|
try {
|
|
6037
5685
|
const token = bearerToken(source.credentials);
|
|
6038
|
-
const res = await fetch(`${
|
|
5686
|
+
const res = await fetch(`${API6}/v1/outbound?limit=1`, {
|
|
6039
5687
|
headers: { authorization: `Bearer ${token}` },
|
|
6040
5688
|
signal: AbortSignal.timeout(8e3)
|
|
6041
5689
|
});
|
|
@@ -6180,9 +5828,9 @@ var INGEST_FIELDS = [
|
|
|
6180
5828
|
|
|
6181
5829
|
// src/connectors/adapters/whatsapp-business.ts
|
|
6182
5830
|
var SCOPES5 = ["whatsapp_business_messaging", "whatsapp_business_management", "business_management"];
|
|
6183
|
-
var
|
|
6184
|
-
var
|
|
6185
|
-
var
|
|
5831
|
+
var AUTH_URL8 = "https://www.facebook.com/v21.0/dialog/oauth";
|
|
5832
|
+
var TOKEN_URL8 = "https://graph.facebook.com/v21.0/oauth/access_token";
|
|
5833
|
+
var API7 = "https://graph.facebook.com/v21.0";
|
|
6186
5834
|
function whatsappBusiness(opts) {
|
|
6187
5835
|
const { clientId, clientSecret } = opts;
|
|
6188
5836
|
const adapter = {
|
|
@@ -6192,8 +5840,8 @@ function whatsappBusiness(opts) {
|
|
|
6192
5840
|
description: "Send text and template messages from a verified WhatsApp Business number, and read your approved message templates. Advisory surface \u2014 WhatsApp sends are append-only.",
|
|
6193
5841
|
auth: {
|
|
6194
5842
|
kind: "oauth2",
|
|
6195
|
-
authorizationUrl:
|
|
6196
|
-
tokenUrl:
|
|
5843
|
+
authorizationUrl: AUTH_URL8,
|
|
5844
|
+
tokenUrl: TOKEN_URL8,
|
|
6197
5845
|
scopes: SCOPES5,
|
|
6198
5846
|
clientIdEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_ID",
|
|
6199
5847
|
clientSecretEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_SECRET"
|
|
@@ -6330,12 +5978,12 @@ function whatsappBusiness(opts) {
|
|
|
6330
5978
|
async executeRead(inv) {
|
|
6331
5979
|
const accessToken = readAccessToken(inv.source.credentials);
|
|
6332
5980
|
if (inv.capabilityName === "list_message_templates") {
|
|
6333
|
-
const wabaId =
|
|
5981
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6334
5982
|
const { limit, status } = inv.args;
|
|
6335
5983
|
const params = new URLSearchParams();
|
|
6336
5984
|
params.set("limit", String(Math.min(Math.max(1, limit ?? 50), 200)));
|
|
6337
5985
|
if (status) params.set("status", status);
|
|
6338
|
-
const url = `${
|
|
5986
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
|
|
6339
5987
|
const json = await graphGet(url, accessToken, inv.source.id);
|
|
6340
5988
|
const data = json.data ?? [];
|
|
6341
5989
|
return {
|
|
@@ -6352,11 +6000,11 @@ function whatsappBusiness(opts) {
|
|
|
6352
6000
|
};
|
|
6353
6001
|
}
|
|
6354
6002
|
if (inv.capabilityName === "get_business_phone_number") {
|
|
6355
|
-
const phoneNumberId =
|
|
6003
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6356
6004
|
const params = new URLSearchParams({
|
|
6357
6005
|
fields: "display_phone_number,verified_name,quality_rating,code_verification_status,platform_type"
|
|
6358
6006
|
});
|
|
6359
|
-
const url = `${
|
|
6007
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}?${params.toString()}`;
|
|
6360
6008
|
const json = await graphGet(url, accessToken, inv.source.id);
|
|
6361
6009
|
return {
|
|
6362
6010
|
data: {
|
|
@@ -6382,8 +6030,8 @@ function whatsappBusiness(opts) {
|
|
|
6382
6030
|
if (inv.capabilityName === "templates.delete") {
|
|
6383
6031
|
return deleteTemplate(inv, accessToken);
|
|
6384
6032
|
}
|
|
6385
|
-
const phoneNumberId =
|
|
6386
|
-
const url = `${
|
|
6033
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6034
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}/messages`;
|
|
6387
6035
|
let body;
|
|
6388
6036
|
if (inv.capabilityName === "send_text_message") {
|
|
6389
6037
|
const { to, body: text, previewUrl } = inv.args;
|
|
@@ -6464,7 +6112,7 @@ function whatsappBusiness(opts) {
|
|
|
6464
6112
|
throw new Error("WhatsApp Business OAuth client not configured (WHATSAPP_BUSINESS_OAUTH_CLIENT_ID / _SECRET)");
|
|
6465
6113
|
}
|
|
6466
6114
|
const tokens = await exchangeAuthorizationCode({
|
|
6467
|
-
tokenUrl:
|
|
6115
|
+
tokenUrl: TOKEN_URL8,
|
|
6468
6116
|
clientId,
|
|
6469
6117
|
clientSecret,
|
|
6470
6118
|
code: input.code,
|
|
@@ -6488,7 +6136,7 @@ function whatsappBusiness(opts) {
|
|
|
6488
6136
|
try {
|
|
6489
6137
|
const accessToken = readAccessToken(source.credentials);
|
|
6490
6138
|
const phoneNumberId = typeof source.metadata.phoneNumberId === "string" ? source.metadata.phoneNumberId : void 0;
|
|
6491
|
-
const probeUrl = phoneNumberId ? `${
|
|
6139
|
+
const probeUrl = phoneNumberId ? `${API7}/${encodeURIComponent(phoneNumberId)}?fields=display_phone_number` : `${API7}/me?fields=id`;
|
|
6492
6140
|
const res = await fetch(probeUrl, {
|
|
6493
6141
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
6494
6142
|
signal: AbortSignal.timeout(8e3)
|
|
@@ -6512,7 +6160,7 @@ function readAccessToken(creds) {
|
|
|
6512
6160
|
}
|
|
6513
6161
|
return creds.accessToken;
|
|
6514
6162
|
}
|
|
6515
|
-
function
|
|
6163
|
+
function readMetaString4(meta, key) {
|
|
6516
6164
|
const v = meta[key];
|
|
6517
6165
|
if (typeof v !== "string" || v.length === 0) {
|
|
6518
6166
|
throw new Error(`whatsapp-business DataSource.metadata.${key} is missing \u2014 set it at connect-time from the Embedded Signup callback`);
|
|
@@ -6541,7 +6189,7 @@ function decodeBase64(value) {
|
|
|
6541
6189
|
return bytes;
|
|
6542
6190
|
}
|
|
6543
6191
|
async function uploadMedia(inv, accessToken) {
|
|
6544
|
-
const phoneNumberId =
|
|
6192
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6545
6193
|
const { dataBase64, mimeType, filename } = inv.args;
|
|
6546
6194
|
if (typeof dataBase64 !== "string" || dataBase64.length === 0) {
|
|
6547
6195
|
throw new Error("whatsapp-business media.upload: dataBase64 is required");
|
|
@@ -6554,7 +6202,7 @@ async function uploadMedia(inv, accessToken) {
|
|
|
6554
6202
|
form.set("messaging_product", "whatsapp");
|
|
6555
6203
|
form.set("type", mimeType);
|
|
6556
6204
|
form.set("file", new Blob([bytes], { type: mimeType }), filename ?? "upload");
|
|
6557
|
-
const url = `${
|
|
6205
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}/media`;
|
|
6558
6206
|
const res = await fetch(url, {
|
|
6559
6207
|
method: "POST",
|
|
6560
6208
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
@@ -6577,7 +6225,7 @@ async function uploadMedia(inv, accessToken) {
|
|
|
6577
6225
|
};
|
|
6578
6226
|
}
|
|
6579
6227
|
async function createTemplate(inv, accessToken) {
|
|
6580
|
-
const wabaId =
|
|
6228
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6581
6229
|
const { name, language, category, components } = inv.args;
|
|
6582
6230
|
if (typeof name !== "string" || name.length === 0) {
|
|
6583
6231
|
throw new Error("whatsapp-business templates.create: name is required");
|
|
@@ -6591,7 +6239,7 @@ async function createTemplate(inv, accessToken) {
|
|
|
6591
6239
|
if (!Array.isArray(components)) {
|
|
6592
6240
|
throw new Error("whatsapp-business templates.create: components must be an array");
|
|
6593
6241
|
}
|
|
6594
|
-
const url = `${
|
|
6242
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates`;
|
|
6595
6243
|
const res = await fetch(url, {
|
|
6596
6244
|
method: "POST",
|
|
6597
6245
|
headers: {
|
|
@@ -6617,7 +6265,7 @@ async function createTemplate(inv, accessToken) {
|
|
|
6617
6265
|
};
|
|
6618
6266
|
}
|
|
6619
6267
|
async function deleteTemplate(inv, accessToken) {
|
|
6620
|
-
const wabaId =
|
|
6268
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6621
6269
|
const { name, hsmId } = inv.args;
|
|
6622
6270
|
if (typeof name !== "string" || name.length === 0) {
|
|
6623
6271
|
throw new Error("whatsapp-business templates.delete: name is required");
|
|
@@ -6625,7 +6273,7 @@ async function deleteTemplate(inv, accessToken) {
|
|
|
6625
6273
|
const params = new URLSearchParams();
|
|
6626
6274
|
params.set("name", name);
|
|
6627
6275
|
if (typeof hsmId === "string" && hsmId.length > 0) params.set("hsm_id", hsmId);
|
|
6628
|
-
const url = `${
|
|
6276
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
|
|
6629
6277
|
const res = await fetch(url, {
|
|
6630
6278
|
method: "DELETE",
|
|
6631
6279
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
@@ -6648,7 +6296,7 @@ async function deleteTemplate(inv, accessToken) {
|
|
|
6648
6296
|
}
|
|
6649
6297
|
|
|
6650
6298
|
// src/connectors/adapters/stripe-pack.ts
|
|
6651
|
-
var
|
|
6299
|
+
var API8 = "https://api.stripe.com/v1";
|
|
6652
6300
|
var stripePackConnector = {
|
|
6653
6301
|
manifest: {
|
|
6654
6302
|
kind: "stripe-pack",
|
|
@@ -6848,7 +6496,7 @@ var stripePackConnector = {
|
|
|
6848
6496
|
throw new Error(`stripe-pack: unknown read capability ${inv.capabilityName}`);
|
|
6849
6497
|
}
|
|
6850
6498
|
const { email } = inv.args;
|
|
6851
|
-
const url = `${
|
|
6499
|
+
const url = `${API8}/customers/search?query=${encodeURIComponent(`email:'${email.toLowerCase()}'`)}&limit=1`;
|
|
6852
6500
|
const res = await fetch(url, {
|
|
6853
6501
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
6854
6502
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -6881,7 +6529,7 @@ var stripePackConnector = {
|
|
|
6881
6529
|
async test(source) {
|
|
6882
6530
|
try {
|
|
6883
6531
|
const apiKey = readApiKey(source.credentials);
|
|
6884
|
-
const res = await fetch(`${
|
|
6532
|
+
const res = await fetch(`${API8}/account`, {
|
|
6885
6533
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
6886
6534
|
signal: AbortSignal.timeout(8e3)
|
|
6887
6535
|
});
|
|
@@ -6907,7 +6555,7 @@ async function createInvoice(inv, apiKey) {
|
|
|
6907
6555
|
quantity: String(it.quantity ?? 1)
|
|
6908
6556
|
});
|
|
6909
6557
|
if (it.description) body.set("description", it.description);
|
|
6910
|
-
const res = await fetch(`${
|
|
6558
|
+
const res = await fetch(`${API8}/invoiceitems`, {
|
|
6911
6559
|
method: "POST",
|
|
6912
6560
|
headers: {
|
|
6913
6561
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -6932,7 +6580,7 @@ async function createInvoice(inv, apiKey) {
|
|
|
6932
6580
|
collection_method: "send_invoice",
|
|
6933
6581
|
days_until_due: "14"
|
|
6934
6582
|
});
|
|
6935
|
-
const invRes = await fetch(`${
|
|
6583
|
+
const invRes = await fetch(`${API8}/invoices`, {
|
|
6936
6584
|
method: "POST",
|
|
6937
6585
|
headers: {
|
|
6938
6586
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -6970,7 +6618,7 @@ async function createCheckoutSession(inv, apiKey) {
|
|
|
6970
6618
|
body.set(`line_items[${i}][price]`, it.price);
|
|
6971
6619
|
body.set(`line_items[${i}][quantity]`, String(it.quantity ?? 1));
|
|
6972
6620
|
});
|
|
6973
|
-
const res = await fetch(`${
|
|
6621
|
+
const res = await fetch(`${API8}/checkout/sessions`, {
|
|
6974
6622
|
method: "POST",
|
|
6975
6623
|
headers: {
|
|
6976
6624
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7001,7 +6649,7 @@ async function listSubscriptions(inv, apiKey) {
|
|
|
7001
6649
|
const params = new URLSearchParams({ customer: customerId, limit: String(limit ?? 10) });
|
|
7002
6650
|
if (status && status !== "all") params.set("status", status);
|
|
7003
6651
|
else params.set("status", "all");
|
|
7004
|
-
const res = await fetch(`${
|
|
6652
|
+
const res = await fetch(`${API8}/subscriptions?${params.toString()}`, {
|
|
7005
6653
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
7006
6654
|
signal: AbortSignal.timeout(1e4)
|
|
7007
6655
|
});
|
|
@@ -7036,7 +6684,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7036
6684
|
let res;
|
|
7037
6685
|
if (atPeriodEnd) {
|
|
7038
6686
|
const body = new URLSearchParams({ cancel_at_period_end: "true" });
|
|
7039
|
-
res = await fetch(`${
|
|
6687
|
+
res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
|
|
7040
6688
|
method: "POST",
|
|
7041
6689
|
headers: {
|
|
7042
6690
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7047,7 +6695,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7047
6695
|
signal: AbortSignal.timeout(15e3)
|
|
7048
6696
|
});
|
|
7049
6697
|
} else {
|
|
7050
|
-
res = await fetch(`${
|
|
6698
|
+
res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
|
|
7051
6699
|
method: "DELETE",
|
|
7052
6700
|
headers: {
|
|
7053
6701
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7082,7 +6730,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7082
6730
|
async function createBillingPortalSession(inv, apiKey) {
|
|
7083
6731
|
const { customerId, returnUrl } = inv.args;
|
|
7084
6732
|
const body = new URLSearchParams({ customer: customerId, return_url: returnUrl });
|
|
7085
|
-
const res = await fetch(`${
|
|
6733
|
+
const res = await fetch(`${API8}/billing_portal/sessions`, {
|
|
7086
6734
|
method: "POST",
|
|
7087
6735
|
headers: {
|
|
7088
6736
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7130,7 +6778,7 @@ async function createPaymentIntent(inv, apiKey) {
|
|
|
7130
6778
|
body.set(`metadata[${k}]`, String(v));
|
|
7131
6779
|
}
|
|
7132
6780
|
}
|
|
7133
|
-
const res = await fetch(`${
|
|
6781
|
+
const res = await fetch(`${API8}/payment_intents`, {
|
|
7134
6782
|
method: "POST",
|
|
7135
6783
|
headers: {
|
|
7136
6784
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7178,7 +6826,7 @@ async function createRefund(inv, apiKey) {
|
|
|
7178
6826
|
if (args.charge) body.set("charge", args.charge);
|
|
7179
6827
|
if (typeof args.amount === "number") body.set("amount", String(args.amount));
|
|
7180
6828
|
if (args.reason) body.set("reason", args.reason);
|
|
7181
|
-
const res = await fetch(`${
|
|
6829
|
+
const res = await fetch(`${API8}/refunds`, {
|
|
7182
6830
|
method: "POST",
|
|
7183
6831
|
headers: {
|
|
7184
6832
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7226,7 +6874,7 @@ async function createCustomer(inv, apiKey) {
|
|
|
7226
6874
|
body.set(`metadata[${k}]`, String(v));
|
|
7227
6875
|
}
|
|
7228
6876
|
}
|
|
7229
|
-
const res = await fetch(`${
|
|
6877
|
+
const res = await fetch(`${API8}/customers`, {
|
|
7230
6878
|
method: "POST",
|
|
7231
6879
|
headers: {
|
|
7232
6880
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7302,7 +6950,7 @@ var webhookConnector = {
|
|
|
7302
6950
|
]
|
|
7303
6951
|
},
|
|
7304
6952
|
async executeRead(inv) {
|
|
7305
|
-
const url =
|
|
6953
|
+
const url = readMetaString5(inv.source.metadata, "url");
|
|
7306
6954
|
const params = inv.args && typeof inv.args === "object" ? inv.args : {};
|
|
7307
6955
|
const u = new URL(url);
|
|
7308
6956
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -7324,7 +6972,7 @@ var webhookConnector = {
|
|
|
7324
6972
|
};
|
|
7325
6973
|
},
|
|
7326
6974
|
async executeMutation(inv) {
|
|
7327
|
-
const url =
|
|
6975
|
+
const url = readMetaString5(inv.source.metadata, "url");
|
|
7328
6976
|
const body = JSON.stringify(inv.args ?? {});
|
|
7329
6977
|
const res = await fetch(url, {
|
|
7330
6978
|
method: "POST",
|
|
@@ -7354,7 +7002,7 @@ var webhookConnector = {
|
|
|
7354
7002
|
},
|
|
7355
7003
|
async test(source) {
|
|
7356
7004
|
try {
|
|
7357
|
-
const url =
|
|
7005
|
+
const url = readMetaString5(source.metadata, "url");
|
|
7358
7006
|
const res = await fetch(url, {
|
|
7359
7007
|
method: "HEAD",
|
|
7360
7008
|
headers: signHeaders(source.credentials, "", `health-${Date.now()}`),
|
|
@@ -7367,7 +7015,7 @@ var webhookConnector = {
|
|
|
7367
7015
|
}
|
|
7368
7016
|
}
|
|
7369
7017
|
};
|
|
7370
|
-
function
|
|
7018
|
+
function readMetaString5(meta, key) {
|
|
7371
7019
|
const v = meta[key];
|
|
7372
7020
|
if (typeof v !== "string" || v.length === 0) {
|
|
7373
7021
|
throw new Error(`webhook DataSource.metadata.${key} is missing`);
|
|
@@ -37415,8 +37063,8 @@ var SCOPES7 = [
|
|
|
37415
37063
|
"request_signature",
|
|
37416
37064
|
"signature_request_access"
|
|
37417
37065
|
];
|
|
37418
|
-
var
|
|
37419
|
-
var
|
|
37066
|
+
var AUTH_URL9 = "https://app.hellosign.com/oauth/authorize";
|
|
37067
|
+
var TOKEN_URL9 = "https://app.hellosign.com/oauth/token";
|
|
37420
37068
|
var DEFAULT_API_BASE = "https://api.hellosign.com/v3";
|
|
37421
37069
|
function hellosign(opts) {
|
|
37422
37070
|
const { clientId, clientSecret } = opts;
|
|
@@ -37429,8 +37077,8 @@ function hellosign(opts) {
|
|
|
37429
37077
|
description: "Send documents for e-signature via Dropbox Sign templates, poll signature-request status, cancel in-flight requests, and react to push events when signers complete.",
|
|
37430
37078
|
auth: {
|
|
37431
37079
|
kind: "oauth2",
|
|
37432
|
-
authorizationUrl:
|
|
37433
|
-
tokenUrl:
|
|
37080
|
+
authorizationUrl: AUTH_URL9,
|
|
37081
|
+
tokenUrl: TOKEN_URL9,
|
|
37434
37082
|
scopes: SCOPES7,
|
|
37435
37083
|
clientIdEnv: "HELLOSIGN_OAUTH_CLIENT_ID",
|
|
37436
37084
|
clientSecretEnv: "HELLOSIGN_OAUTH_CLIENT_SECRET",
|
|
@@ -37587,7 +37235,7 @@ function hellosign(opts) {
|
|
|
37587
37235
|
throw new Error("Dropbox Sign OAuth client not configured (HELLOSIGN_OAUTH_CLIENT_ID / _SECRET)");
|
|
37588
37236
|
}
|
|
37589
37237
|
const tokens = await exchangeAuthorizationCode({
|
|
37590
|
-
tokenUrl:
|
|
37238
|
+
tokenUrl: TOKEN_URL9,
|
|
37591
37239
|
clientId,
|
|
37592
37240
|
clientSecret,
|
|
37593
37241
|
code: input.code,
|
|
@@ -37610,7 +37258,7 @@ function hellosign(opts) {
|
|
|
37610
37258
|
throw new Error("hellosign.refreshToken: missing refresh token");
|
|
37611
37259
|
}
|
|
37612
37260
|
const refreshed = await refreshAccessToken({
|
|
37613
|
-
tokenUrl:
|
|
37261
|
+
tokenUrl: TOKEN_URL9,
|
|
37614
37262
|
clientId,
|
|
37615
37263
|
clientSecret,
|
|
37616
37264
|
refreshToken: creds.refreshToken
|
|
@@ -37872,23 +37520,27 @@ function parseInboundBody(rawBody) {
|
|
|
37872
37520
|
if (json && typeof json === "object") return json;
|
|
37873
37521
|
} catch {
|
|
37874
37522
|
}
|
|
37875
|
-
const
|
|
37876
|
-
if (
|
|
37523
|
+
const formJson = new URLSearchParams(rawBody).get("json");
|
|
37524
|
+
if (formJson) {
|
|
37877
37525
|
try {
|
|
37878
|
-
return JSON.parse(
|
|
37526
|
+
return JSON.parse(formJson);
|
|
37879
37527
|
} catch {
|
|
37880
37528
|
return null;
|
|
37881
37529
|
}
|
|
37882
37530
|
}
|
|
37883
|
-
const
|
|
37884
|
-
if (
|
|
37885
|
-
|
|
37886
|
-
|
|
37887
|
-
|
|
37888
|
-
|
|
37889
|
-
|
|
37531
|
+
const nameIdx = rawBody.indexOf('name="json"');
|
|
37532
|
+
if (nameIdx === -1) return null;
|
|
37533
|
+
const afterName = rawBody.slice(nameIdx);
|
|
37534
|
+
const sep = /\r?\n\r?\n/.exec(afterName);
|
|
37535
|
+
if (!sep) return null;
|
|
37536
|
+
const partBody = afterName.slice(sep.index + sep[0].length);
|
|
37537
|
+
const end = /\r?\n--/.exec(partBody);
|
|
37538
|
+
if (!end) return null;
|
|
37539
|
+
try {
|
|
37540
|
+
return JSON.parse(partBody.slice(0, end.index));
|
|
37541
|
+
} catch {
|
|
37542
|
+
return null;
|
|
37890
37543
|
}
|
|
37891
|
-
return null;
|
|
37892
37544
|
}
|
|
37893
37545
|
async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
37894
37546
|
if (creds.kind !== "oauth2") {
|
|
@@ -37901,7 +37553,7 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37901
37553
|
throw new CredentialsExpired("Dropbox Sign access token expired and no refresh token", inv?.source.id ?? "");
|
|
37902
37554
|
}
|
|
37903
37555
|
const refreshed = await refreshAccessToken({
|
|
37904
|
-
tokenUrl:
|
|
37556
|
+
tokenUrl: TOKEN_URL9,
|
|
37905
37557
|
clientId,
|
|
37906
37558
|
clientSecret,
|
|
37907
37559
|
refreshToken: creds.refreshToken
|
|
@@ -37920,12 +37572,12 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37920
37572
|
|
|
37921
37573
|
// src/connectors/adapters/pandadoc.ts
|
|
37922
37574
|
var SCOPES8 = ["read", "read+write"];
|
|
37923
|
-
var
|
|
37924
|
-
var
|
|
37925
|
-
var
|
|
37575
|
+
var AUTH_URL10 = "https://app.pandadoc.com/oauth2/authorize";
|
|
37576
|
+
var TOKEN_URL10 = "https://api.pandadoc.com/oauth2/access_token";
|
|
37577
|
+
var API9 = "https://api.pandadoc.com/public/v1";
|
|
37926
37578
|
function pandadoc(opts) {
|
|
37927
37579
|
const { clientId, clientSecret } = opts;
|
|
37928
|
-
const baseUrl = (opts.baseUrl ??
|
|
37580
|
+
const baseUrl = (opts.baseUrl ?? API9).replace(/\/$/, "");
|
|
37929
37581
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
37930
37582
|
const adapter = {
|
|
37931
37583
|
manifest: {
|
|
@@ -37934,8 +37586,8 @@ function pandadoc(opts) {
|
|
|
37934
37586
|
description: "Draft contracts and proposals from PandaDoc templates, send them for signature, poll signing status, and cancel in-flight documents.",
|
|
37935
37587
|
auth: {
|
|
37936
37588
|
kind: "oauth2",
|
|
37937
|
-
authorizationUrl:
|
|
37938
|
-
tokenUrl:
|
|
37589
|
+
authorizationUrl: AUTH_URL10,
|
|
37590
|
+
tokenUrl: TOKEN_URL10,
|
|
37939
37591
|
scopes: SCOPES8,
|
|
37940
37592
|
clientIdEnv: "PANDADOC_OAUTH_CLIENT_ID",
|
|
37941
37593
|
clientSecretEnv: "PANDADOC_OAUTH_CLIENT_SECRET"
|
|
@@ -38083,7 +37735,7 @@ function pandadoc(opts) {
|
|
|
38083
37735
|
throw new Error("PandaDoc OAuth client not configured (PANDADOC_OAUTH_CLIENT_ID / _SECRET)");
|
|
38084
37736
|
}
|
|
38085
37737
|
const tokens = await exchangeAuthorizationCode({
|
|
38086
|
-
tokenUrl:
|
|
37738
|
+
tokenUrl: TOKEN_URL10,
|
|
38087
37739
|
clientId,
|
|
38088
37740
|
clientSecret,
|
|
38089
37741
|
code: input.code,
|
|
@@ -38106,7 +37758,7 @@ function pandadoc(opts) {
|
|
|
38106
37758
|
throw new Error("pandadoc.refreshToken: missing refresh token");
|
|
38107
37759
|
}
|
|
38108
37760
|
const refreshed = await refreshAccessToken({
|
|
38109
|
-
tokenUrl:
|
|
37761
|
+
tokenUrl: TOKEN_URL10,
|
|
38110
37762
|
clientId,
|
|
38111
37763
|
clientSecret,
|
|
38112
37764
|
refreshToken: creds.refreshToken
|
|
@@ -38414,7 +38066,7 @@ async function ensureFreshAccessTokenFromCreds(creds, clientId, clientSecret, on
|
|
|
38414
38066
|
throw new CredentialsExpired("PandaDoc access token expired and no refresh token", "");
|
|
38415
38067
|
}
|
|
38416
38068
|
const refreshed = await refreshAccessToken({
|
|
38417
|
-
tokenUrl:
|
|
38069
|
+
tokenUrl: TOKEN_URL10,
|
|
38418
38070
|
clientId,
|
|
38419
38071
|
clientSecret,
|
|
38420
38072
|
refreshToken: creds.refreshToken
|
|
@@ -38438,9 +38090,9 @@ var SCOPES9 = [
|
|
|
38438
38090
|
"https://www.googleapis.com/auth/documents",
|
|
38439
38091
|
"https://www.googleapis.com/auth/drive.file"
|
|
38440
38092
|
];
|
|
38441
|
-
var
|
|
38442
|
-
var
|
|
38443
|
-
var
|
|
38093
|
+
var AUTH_URL11 = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
38094
|
+
var TOKEN_URL11 = "https://oauth2.googleapis.com/token";
|
|
38095
|
+
var API10 = "https://docs.googleapis.com/v1";
|
|
38444
38096
|
var DRIVE_API = "https://www.googleapis.com/drive/v3";
|
|
38445
38097
|
var EXPORT_MIME = {
|
|
38446
38098
|
pdf: "application/pdf",
|
|
@@ -38464,8 +38116,8 @@ function googleDocs(opts) {
|
|
|
38464
38116
|
description: "Read and draft into the user's Google Docs. Fetch a document's plaintext body, create a new doc from a title + initial body, and append text with optional revision-id CAS guarding concurrent edits.",
|
|
38465
38117
|
auth: {
|
|
38466
38118
|
kind: "oauth2",
|
|
38467
|
-
authorizationUrl:
|
|
38468
|
-
tokenUrl:
|
|
38119
|
+
authorizationUrl: AUTH_URL11,
|
|
38120
|
+
tokenUrl: TOKEN_URL11,
|
|
38469
38121
|
scopes: SCOPES9,
|
|
38470
38122
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38471
38123
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -38579,7 +38231,7 @@ function googleDocs(opts) {
|
|
|
38579
38231
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
38580
38232
|
}
|
|
38581
38233
|
const tokens = await exchangeAuthorizationCode({
|
|
38582
|
-
tokenUrl:
|
|
38234
|
+
tokenUrl: TOKEN_URL11,
|
|
38583
38235
|
clientId,
|
|
38584
38236
|
clientSecret,
|
|
38585
38237
|
code: input.code,
|
|
@@ -38602,7 +38254,7 @@ function googleDocs(opts) {
|
|
|
38602
38254
|
throw new Error("google-docs.refreshToken: missing refresh token");
|
|
38603
38255
|
}
|
|
38604
38256
|
const refreshed = await refreshAccessToken({
|
|
38605
|
-
tokenUrl:
|
|
38257
|
+
tokenUrl: TOKEN_URL11,
|
|
38606
38258
|
clientId,
|
|
38607
38259
|
clientSecret,
|
|
38608
38260
|
refreshToken: creds.refreshToken
|
|
@@ -38656,7 +38308,7 @@ function findAppendIndex(doc) {
|
|
|
38656
38308
|
}
|
|
38657
38309
|
async function getDocument2(inv, accessToken, timeoutMs) {
|
|
38658
38310
|
const { documentId } = inv.args ?? {};
|
|
38659
|
-
const res = await fetch(`${
|
|
38311
|
+
const res = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}`, {
|
|
38660
38312
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38661
38313
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38662
38314
|
});
|
|
@@ -38690,7 +38342,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38690
38342
|
if (!title || typeof title !== "string") {
|
|
38691
38343
|
throw new Error("google-docs create_document: title is required");
|
|
38692
38344
|
}
|
|
38693
|
-
const createRes = await fetch(`${
|
|
38345
|
+
const createRes = await fetch(`${API10}/documents`, {
|
|
38694
38346
|
method: "POST",
|
|
38695
38347
|
headers: {
|
|
38696
38348
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -38710,7 +38362,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38710
38362
|
let revisionId = created.revisionId;
|
|
38711
38363
|
if (typeof body === "string" && body.length > 0) {
|
|
38712
38364
|
const insertRes = await fetch(
|
|
38713
|
-
`${
|
|
38365
|
+
`${API10}/documents/${encodeURIComponent(created.documentId)}:batchUpdate`,
|
|
38714
38366
|
{
|
|
38715
38367
|
method: "POST",
|
|
38716
38368
|
headers: {
|
|
@@ -38753,7 +38405,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38753
38405
|
if (!text) {
|
|
38754
38406
|
throw new Error("google-docs append_text: text is required");
|
|
38755
38407
|
}
|
|
38756
|
-
const docRes = await fetch(`${
|
|
38408
|
+
const docRes = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}?fields=documentId,revisionId,body(content(endIndex))`, {
|
|
38757
38409
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38758
38410
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38759
38411
|
});
|
|
@@ -38783,7 +38435,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38783
38435
|
body.writeControl = { requiredRevisionId };
|
|
38784
38436
|
}
|
|
38785
38437
|
const res = await fetch(
|
|
38786
|
-
`${
|
|
38438
|
+
`${API10}/documents/${encodeURIComponent(documentId)}:batchUpdate`,
|
|
38787
38439
|
{
|
|
38788
38440
|
method: "POST",
|
|
38789
38441
|
headers: {
|
|
@@ -38904,7 +38556,7 @@ async function ensureFreshAccessToken9(creds, clientId, clientSecret) {
|
|
|
38904
38556
|
throw new CredentialsExpired("Google Docs access token expired and no refresh token", "");
|
|
38905
38557
|
}
|
|
38906
38558
|
const refreshed = await refreshAccessToken({
|
|
38907
|
-
tokenUrl:
|
|
38559
|
+
tokenUrl: TOKEN_URL11,
|
|
38908
38560
|
clientId,
|
|
38909
38561
|
clientSecret,
|
|
38910
38562
|
refreshToken: creds.refreshToken
|
|
@@ -38922,9 +38574,9 @@ var SCOPES10 = [
|
|
|
38922
38574
|
"https://www.googleapis.com/auth/forms.responses.readonly",
|
|
38923
38575
|
SCOPE_WRITE3
|
|
38924
38576
|
];
|
|
38925
|
-
var
|
|
38926
|
-
var
|
|
38927
|
-
var
|
|
38577
|
+
var AUTH_URL12 = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
38578
|
+
var TOKEN_URL12 = "https://oauth2.googleapis.com/token";
|
|
38579
|
+
var API11 = "https://forms.googleapis.com/v1";
|
|
38928
38580
|
function googleForms(opts) {
|
|
38929
38581
|
const { clientId, clientSecret } = opts;
|
|
38930
38582
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -38935,8 +38587,8 @@ function googleForms(opts) {
|
|
|
38935
38587
|
description: "Read a Google Form's schema and paginate its responses for KB ingest, lead routing, or analytics. Returns answers keyed by questionId with the original item tree available for question\u2192title joins.",
|
|
38936
38588
|
auth: {
|
|
38937
38589
|
kind: "oauth2",
|
|
38938
|
-
authorizationUrl:
|
|
38939
|
-
tokenUrl:
|
|
38590
|
+
authorizationUrl: AUTH_URL12,
|
|
38591
|
+
tokenUrl: TOKEN_URL12,
|
|
38940
38592
|
scopes: SCOPES10,
|
|
38941
38593
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38942
38594
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -39080,7 +38732,7 @@ function googleForms(opts) {
|
|
|
39080
38732
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
39081
38733
|
}
|
|
39082
38734
|
const tokens = await exchangeAuthorizationCode({
|
|
39083
|
-
tokenUrl:
|
|
38735
|
+
tokenUrl: TOKEN_URL12,
|
|
39084
38736
|
clientId,
|
|
39085
38737
|
clientSecret,
|
|
39086
38738
|
code: input.code,
|
|
@@ -39103,7 +38755,7 @@ function googleForms(opts) {
|
|
|
39103
38755
|
throw new Error("google-forms.refreshToken: missing refresh token");
|
|
39104
38756
|
}
|
|
39105
38757
|
const refreshed = await refreshAccessToken({
|
|
39106
|
-
tokenUrl:
|
|
38758
|
+
tokenUrl: TOKEN_URL12,
|
|
39107
38759
|
clientId,
|
|
39108
38760
|
clientSecret,
|
|
39109
38761
|
refreshToken: creds.refreshToken
|
|
@@ -39149,7 +38801,7 @@ function flattenAnswers(answers) {
|
|
|
39149
38801
|
async function getForm(inv, accessToken, timeoutMs) {
|
|
39150
38802
|
const { formId } = inv.args ?? {};
|
|
39151
38803
|
if (!formId) throw new Error("google-forms get_form: formId is required");
|
|
39152
|
-
const res = await fetch(`${
|
|
38804
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}`, {
|
|
39153
38805
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39154
38806
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39155
38807
|
});
|
|
@@ -39184,7 +38836,7 @@ async function listResponses(inv, accessToken, timeoutMs) {
|
|
|
39184
38836
|
if (pageToken) params.set("pageToken", pageToken);
|
|
39185
38837
|
if (filter) params.set("filter", filter);
|
|
39186
38838
|
const qs = params.toString();
|
|
39187
|
-
const url = `${
|
|
38839
|
+
const url = `${API11}/forms/${encodeURIComponent(formId)}/responses${qs ? `?${qs}` : ""}`;
|
|
39188
38840
|
const res = await fetch(url, {
|
|
39189
38841
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39190
38842
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39221,7 +38873,7 @@ async function getResponse(inv, accessToken, timeoutMs) {
|
|
|
39221
38873
|
if (!formId) throw new Error("google-forms get_response: formId is required");
|
|
39222
38874
|
if (!responseId) throw new Error("google-forms get_response: responseId is required");
|
|
39223
38875
|
const res = await fetch(
|
|
39224
|
-
`${
|
|
38876
|
+
`${API11}/forms/${encodeURIComponent(formId)}/responses/${encodeURIComponent(responseId)}`,
|
|
39225
38877
|
{
|
|
39226
38878
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39227
38879
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39255,7 +38907,7 @@ async function createForm(inv, accessToken, timeoutMs) {
|
|
|
39255
38907
|
if (!title) throw new Error("google-forms create_form: title is required");
|
|
39256
38908
|
const info = { title };
|
|
39257
38909
|
if (documentTitle) info.documentTitle = documentTitle;
|
|
39258
|
-
const res = await fetch(`${
|
|
38910
|
+
const res = await fetch(`${API11}/forms`, {
|
|
39259
38911
|
method: "POST",
|
|
39260
38912
|
headers: {
|
|
39261
38913
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39294,7 +38946,7 @@ async function batchUpdate(inv, accessToken, timeoutMs) {
|
|
|
39294
38946
|
const body = { requests };
|
|
39295
38947
|
if (typeof includeFormInResponse === "boolean") body.includeFormInResponse = includeFormInResponse;
|
|
39296
38948
|
if (writeControl) body.writeControl = writeControl;
|
|
39297
|
-
const res = await fetch(`${
|
|
38949
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}:batchUpdate`, {
|
|
39298
38950
|
method: "POST",
|
|
39299
38951
|
headers: {
|
|
39300
38952
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39334,7 +38986,7 @@ async function ensureFreshAccessToken10(creds, clientId, clientSecret) {
|
|
|
39334
38986
|
throw new CredentialsExpired("Google Forms access token expired and no refresh token", "");
|
|
39335
38987
|
}
|
|
39336
38988
|
const refreshed = await refreshAccessToken({
|
|
39337
|
-
tokenUrl:
|
|
38989
|
+
tokenUrl: TOKEN_URL12,
|
|
39338
38990
|
clientId,
|
|
39339
38991
|
clientSecret,
|
|
39340
38992
|
refreshToken: creds.refreshToken
|
|
@@ -39355,8 +39007,8 @@ var SCOPES11 = [
|
|
|
39355
39007
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
39356
39008
|
"offline_access"
|
|
39357
39009
|
];
|
|
39358
|
-
var
|
|
39359
|
-
var
|
|
39010
|
+
var AUTH_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
39011
|
+
var TOKEN_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
39360
39012
|
var GRAPH = "https://graph.microsoft.com/v1.0";
|
|
39361
39013
|
function microsoftGraph(opts) {
|
|
39362
39014
|
const { clientId, clientSecret } = opts;
|
|
@@ -39367,8 +39019,8 @@ function microsoftGraph(opts) {
|
|
|
39367
39019
|
description: "Query the Microsoft 365 directory \u2014 look up users by email, list organizations, enumerate groups, and resolve group membership. Read-only identity surface shared across the Outlook, Teams, SharePoint, and OneDrive adapters.",
|
|
39368
39020
|
auth: {
|
|
39369
39021
|
kind: "oauth2",
|
|
39370
|
-
authorizationUrl:
|
|
39371
|
-
tokenUrl:
|
|
39022
|
+
authorizationUrl: AUTH_URL13,
|
|
39023
|
+
tokenUrl: TOKEN_URL13,
|
|
39372
39024
|
scopes: SCOPES11,
|
|
39373
39025
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39374
39026
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39553,7 +39205,7 @@ function microsoftGraph(opts) {
|
|
|
39553
39205
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39554
39206
|
}
|
|
39555
39207
|
const tokens = await exchangeAuthorizationCode({
|
|
39556
|
-
tokenUrl:
|
|
39208
|
+
tokenUrl: TOKEN_URL13,
|
|
39557
39209
|
clientId,
|
|
39558
39210
|
clientSecret,
|
|
39559
39211
|
code: input.code,
|
|
@@ -39576,7 +39228,7 @@ function microsoftGraph(opts) {
|
|
|
39576
39228
|
throw new Error("microsoft-graph.refreshToken: missing refresh token");
|
|
39577
39229
|
}
|
|
39578
39230
|
const refreshed = await refreshAccessToken({
|
|
39579
|
-
tokenUrl:
|
|
39231
|
+
tokenUrl: TOKEN_URL13,
|
|
39580
39232
|
clientId,
|
|
39581
39233
|
clientSecret,
|
|
39582
39234
|
refreshToken: creds.refreshToken
|
|
@@ -39618,7 +39270,7 @@ async function ensureFreshAccessToken11(creds, clientId, clientSecret) {
|
|
|
39618
39270
|
throw new CredentialsExpired("Microsoft Graph access token expired and no refresh token", "");
|
|
39619
39271
|
}
|
|
39620
39272
|
const refreshed = await refreshAccessToken({
|
|
39621
|
-
tokenUrl:
|
|
39273
|
+
tokenUrl: TOKEN_URL13,
|
|
39622
39274
|
clientId,
|
|
39623
39275
|
clientSecret,
|
|
39624
39276
|
refreshToken: creds.refreshToken
|
|
@@ -39655,9 +39307,9 @@ var SCOPE_READ2 = "https://graph.microsoft.com/Mail.Read";
|
|
|
39655
39307
|
var SCOPE_SEND2 = "https://graph.microsoft.com/Mail.Send";
|
|
39656
39308
|
var SCOPE_RW = "https://graph.microsoft.com/Mail.ReadWrite";
|
|
39657
39309
|
var SCOPE_OFFLINE = "offline_access";
|
|
39658
|
-
var
|
|
39659
|
-
var
|
|
39660
|
-
var
|
|
39310
|
+
var AUTH_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
39311
|
+
var TOKEN_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
39312
|
+
var API12 = "https://graph.microsoft.com/v1.0";
|
|
39661
39313
|
function outlookMail(opts) {
|
|
39662
39314
|
const { clientId, clientSecret } = opts;
|
|
39663
39315
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -39669,8 +39321,8 @@ function outlookMail(opts) {
|
|
|
39669
39321
|
description: "Read inbox messages from a Microsoft 365 / Outlook mailbox, fetch a single message with body + attachment manifest, reply on a conversation, and subscribe to a folder for new mail webhooks.",
|
|
39670
39322
|
auth: {
|
|
39671
39323
|
kind: "oauth2",
|
|
39672
|
-
authorizationUrl:
|
|
39673
|
-
tokenUrl:
|
|
39324
|
+
authorizationUrl: AUTH_URL14,
|
|
39325
|
+
tokenUrl: TOKEN_URL14,
|
|
39674
39326
|
scopes,
|
|
39675
39327
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39676
39328
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39754,6 +39406,19 @@ function outlookMail(opts) {
|
|
|
39754
39406
|
type: "boolean",
|
|
39755
39407
|
default: false,
|
|
39756
39408
|
description: "When true, set Graph body.contentType=HTML and send body as HTML; otherwise text. Graph does NOT auto-derive a plain alternative \u2014 set html only when the body is HTML."
|
|
39409
|
+
},
|
|
39410
|
+
attachments: {
|
|
39411
|
+
type: "array",
|
|
39412
|
+
description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Sent as Graph #microsoft.graph.fileAttachment entries.",
|
|
39413
|
+
items: {
|
|
39414
|
+
type: "object",
|
|
39415
|
+
properties: {
|
|
39416
|
+
name: { type: "string" },
|
|
39417
|
+
contentType: { type: "string" },
|
|
39418
|
+
contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
|
|
39419
|
+
},
|
|
39420
|
+
required: ["name", "contentBytes"]
|
|
39421
|
+
}
|
|
39757
39422
|
}
|
|
39758
39423
|
},
|
|
39759
39424
|
required: ["to", "subject", "body"]
|
|
@@ -39784,6 +39449,19 @@ function outlookMail(opts) {
|
|
|
39784
39449
|
type: "boolean",
|
|
39785
39450
|
default: false,
|
|
39786
39451
|
description: "When true, set Graph body.contentType=HTML; otherwise text."
|
|
39452
|
+
},
|
|
39453
|
+
attachments: {
|
|
39454
|
+
type: "array",
|
|
39455
|
+
description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Stored as Graph #microsoft.graph.fileAttachment entries on the draft.",
|
|
39456
|
+
items: {
|
|
39457
|
+
type: "object",
|
|
39458
|
+
properties: {
|
|
39459
|
+
name: { type: "string" },
|
|
39460
|
+
contentType: { type: "string" },
|
|
39461
|
+
contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
|
|
39462
|
+
},
|
|
39463
|
+
required: ["name", "contentBytes"]
|
|
39464
|
+
}
|
|
39787
39465
|
}
|
|
39788
39466
|
},
|
|
39789
39467
|
required: ["to", "subject", "body"]
|
|
@@ -39806,6 +39484,94 @@ function outlookMail(opts) {
|
|
|
39806
39484
|
},
|
|
39807
39485
|
required: ["notificationUrl"]
|
|
39808
39486
|
}
|
|
39487
|
+
},
|
|
39488
|
+
{
|
|
39489
|
+
name: "forward_message",
|
|
39490
|
+
class: "mutation",
|
|
39491
|
+
description: "Forward an existing message to one or more recipients with an optional comment. Graph POST /me/messages/{id}/forward.",
|
|
39492
|
+
cas: "native-idempotency",
|
|
39493
|
+
externalEffect: true,
|
|
39494
|
+
requiredScopes: [SCOPE_SEND2],
|
|
39495
|
+
parameters: {
|
|
39496
|
+
type: "object",
|
|
39497
|
+
properties: {
|
|
39498
|
+
messageId: { type: "string", description: "Graph message id to forward." },
|
|
39499
|
+
to: {
|
|
39500
|
+
oneOf: [
|
|
39501
|
+
{ type: "string" },
|
|
39502
|
+
{ type: "array", items: { type: "string" } }
|
|
39503
|
+
],
|
|
39504
|
+
description: "Recipient address(es). String OR array of strings."
|
|
39505
|
+
},
|
|
39506
|
+
comment: { type: "string", description: "Optional comment prepended to the forwarded body." }
|
|
39507
|
+
},
|
|
39508
|
+
required: ["messageId", "to"]
|
|
39509
|
+
}
|
|
39510
|
+
},
|
|
39511
|
+
{
|
|
39512
|
+
name: "move_message",
|
|
39513
|
+
class: "mutation",
|
|
39514
|
+
description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive). Graph POST /me/messages/{id}/move; returns the relocated message (new id).",
|
|
39515
|
+
cas: "native-idempotency",
|
|
39516
|
+
externalEffect: true,
|
|
39517
|
+
requiredScopes: [SCOPE_RW],
|
|
39518
|
+
parameters: {
|
|
39519
|
+
type: "object",
|
|
39520
|
+
properties: {
|
|
39521
|
+
messageId: { type: "string", description: "Graph message id to move." },
|
|
39522
|
+
destinationId: { type: "string", description: "Destination folder id or well-known name (inbox, archive, deleteditems, ...)." }
|
|
39523
|
+
},
|
|
39524
|
+
required: ["messageId", "destinationId"]
|
|
39525
|
+
}
|
|
39526
|
+
},
|
|
39527
|
+
{
|
|
39528
|
+
name: "set_labels",
|
|
39529
|
+
class: "mutation",
|
|
39530
|
+
description: "Set the full set of Outlook categories (labels) on a message. Graph PATCH /me/messages/{id} replaces the categories array, so supply the complete desired set (the caller computes adds/removes against the current set).",
|
|
39531
|
+
cas: "optimistic-read-verify",
|
|
39532
|
+
externalEffect: false,
|
|
39533
|
+
requiredScopes: [SCOPE_RW],
|
|
39534
|
+
parameters: {
|
|
39535
|
+
type: "object",
|
|
39536
|
+
properties: {
|
|
39537
|
+
messageId: { type: "string", description: "Graph message id to tag." },
|
|
39538
|
+
categories: {
|
|
39539
|
+
type: "array",
|
|
39540
|
+
items: { type: "string" },
|
|
39541
|
+
description: "Full desired category set. Graph replaces (not merges) the categories array."
|
|
39542
|
+
}
|
|
39543
|
+
},
|
|
39544
|
+
required: ["messageId", "categories"]
|
|
39545
|
+
}
|
|
39546
|
+
},
|
|
39547
|
+
{
|
|
39548
|
+
name: "send_draft",
|
|
39549
|
+
class: "mutation",
|
|
39550
|
+
description: "Send a previously created draft message by id. Graph POST /me/messages/{id}/send. Pairs with create_draft.",
|
|
39551
|
+
cas: "native-idempotency",
|
|
39552
|
+
externalEffect: true,
|
|
39553
|
+
requiredScopes: [SCOPE_SEND2],
|
|
39554
|
+
parameters: {
|
|
39555
|
+
type: "object",
|
|
39556
|
+
properties: {
|
|
39557
|
+
messageId: { type: "string", description: "Graph draft message id to send." }
|
|
39558
|
+
},
|
|
39559
|
+
required: ["messageId"]
|
|
39560
|
+
}
|
|
39561
|
+
},
|
|
39562
|
+
{
|
|
39563
|
+
name: "download_attachment",
|
|
39564
|
+
class: "read",
|
|
39565
|
+
description: "Read an attachment record for a message including base64 contentBytes for file attachments. Graph GET /me/messages/{messageId}/attachments/{attachmentId}. Fills the attachment-bytes gap that read_message defers.",
|
|
39566
|
+
requiredScopes: [SCOPE_READ2],
|
|
39567
|
+
parameters: {
|
|
39568
|
+
type: "object",
|
|
39569
|
+
properties: {
|
|
39570
|
+
messageId: { type: "string", description: "Graph message id owning the attachment." },
|
|
39571
|
+
attachmentId: { type: "string", description: "Graph attachment id (from read_message attachments[].id)." }
|
|
39572
|
+
},
|
|
39573
|
+
required: ["messageId", "attachmentId"]
|
|
39574
|
+
}
|
|
39809
39575
|
}
|
|
39810
39576
|
]
|
|
39811
39577
|
},
|
|
@@ -39813,6 +39579,7 @@ function outlookMail(opts) {
|
|
|
39813
39579
|
const accessToken = await ensureFreshAccessToken12(inv.source.credentials, clientId, clientSecret, inv.onCredentialsRotated);
|
|
39814
39580
|
if (inv.capabilityName === "list_messages") return listMessages2(inv, accessToken, timeoutMs);
|
|
39815
39581
|
if (inv.capabilityName === "read_message") return readMessage2(inv, accessToken, timeoutMs);
|
|
39582
|
+
if (inv.capabilityName === "download_attachment") return downloadAttachment(inv, accessToken, timeoutMs);
|
|
39816
39583
|
throw new Error(`outlook-mail: unknown read capability ${inv.capabilityName}`);
|
|
39817
39584
|
},
|
|
39818
39585
|
async executeMutation(inv) {
|
|
@@ -39821,6 +39588,10 @@ function outlookMail(opts) {
|
|
|
39821
39588
|
if (inv.capabilityName === "send_message") return sendMessage(inv, accessToken, timeoutMs);
|
|
39822
39589
|
if (inv.capabilityName === "create_draft") return createDraft(inv, accessToken, timeoutMs);
|
|
39823
39590
|
if (inv.capabilityName === "subscribe_folder") return subscribeFolder(inv, accessToken, timeoutMs);
|
|
39591
|
+
if (inv.capabilityName === "forward_message") return forwardMessage(inv, accessToken, timeoutMs);
|
|
39592
|
+
if (inv.capabilityName === "move_message") return moveMessage(inv, accessToken, timeoutMs);
|
|
39593
|
+
if (inv.capabilityName === "set_labels") return setLabels(inv, accessToken, timeoutMs);
|
|
39594
|
+
if (inv.capabilityName === "send_draft") return sendDraft(inv, accessToken, timeoutMs);
|
|
39824
39595
|
throw new Error(`outlook-mail: unknown mutation capability ${inv.capabilityName}`);
|
|
39825
39596
|
},
|
|
39826
39597
|
async exchangeOAuth(input) {
|
|
@@ -39828,7 +39599,7 @@ function outlookMail(opts) {
|
|
|
39828
39599
|
throw new Error("Outlook Mail OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39829
39600
|
}
|
|
39830
39601
|
const tokens = await exchangeAuthorizationCode({
|
|
39831
|
-
tokenUrl:
|
|
39602
|
+
tokenUrl: TOKEN_URL14,
|
|
39832
39603
|
clientId,
|
|
39833
39604
|
clientSecret,
|
|
39834
39605
|
code: input.code,
|
|
@@ -39851,7 +39622,7 @@ function outlookMail(opts) {
|
|
|
39851
39622
|
throw new Error("outlook-mail.refreshToken: missing refresh token");
|
|
39852
39623
|
}
|
|
39853
39624
|
const refreshed = await refreshAccessToken({
|
|
39854
|
-
tokenUrl:
|
|
39625
|
+
tokenUrl: TOKEN_URL14,
|
|
39855
39626
|
clientId,
|
|
39856
39627
|
clientSecret,
|
|
39857
39628
|
refreshToken: creds.refreshToken
|
|
@@ -39866,7 +39637,7 @@ function outlookMail(opts) {
|
|
|
39866
39637
|
async test(source) {
|
|
39867
39638
|
try {
|
|
39868
39639
|
const accessToken = await ensureFreshAccessToken12(source.credentials, clientId, clientSecret);
|
|
39869
|
-
const res = await fetch(`${
|
|
39640
|
+
const res = await fetch(`${API12}/me?$select=id,userPrincipalName`, {
|
|
39870
39641
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39871
39642
|
signal: AbortSignal.timeout(8e3)
|
|
39872
39643
|
});
|
|
@@ -39894,7 +39665,7 @@ async function listMessages2(inv, accessToken, timeoutMs) {
|
|
|
39894
39665
|
if (args.skipToken) params.set("$skiptoken", args.skipToken);
|
|
39895
39666
|
const headers = { authorization: `Bearer ${accessToken}` };
|
|
39896
39667
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
39897
|
-
const res = await fetch(`${
|
|
39668
|
+
const res = await fetch(`${API12}/me/mailFolders/${folder}/messages?${params.toString()}`, {
|
|
39898
39669
|
headers,
|
|
39899
39670
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39900
39671
|
});
|
|
@@ -39928,7 +39699,7 @@ function toMessageSummary2(m) {
|
|
|
39928
39699
|
}
|
|
39929
39700
|
async function readMessage2(inv, accessToken, timeoutMs) {
|
|
39930
39701
|
const { id } = inv.args;
|
|
39931
|
-
const url = `${
|
|
39702
|
+
const url = `${API12}/me/messages/${encodeURIComponent(id)}?$expand=attachments($select=id,name,contentType,size,isInline)`;
|
|
39932
39703
|
const res = await fetch(url, {
|
|
39933
39704
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39934
39705
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39971,7 +39742,7 @@ async function readMessage2(inv, accessToken, timeoutMs) {
|
|
|
39971
39742
|
async function sendReply2(inv, accessToken, timeoutMs) {
|
|
39972
39743
|
const { messageId, body, bodyType, replyAll, comment } = inv.args;
|
|
39973
39744
|
const action = replyAll ? "createReplyAll" : "createReply";
|
|
39974
|
-
const draftRes = await fetch(`${
|
|
39745
|
+
const draftRes = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/${action}`, {
|
|
39975
39746
|
method: "POST",
|
|
39976
39747
|
headers: {
|
|
39977
39748
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39994,7 +39765,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
39994
39765
|
{ name: "X-Tangle-Idempotency-Key", value: inv.idempotencyKey }
|
|
39995
39766
|
]
|
|
39996
39767
|
};
|
|
39997
|
-
const patchRes = await fetch(`${
|
|
39768
|
+
const patchRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}`, {
|
|
39998
39769
|
method: "PATCH",
|
|
39999
39770
|
headers: {
|
|
40000
39771
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40010,7 +39781,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
40010
39781
|
const text = await patchRes.text().catch(() => "");
|
|
40011
39782
|
throw new Error(`outlook-mail send_reply patch ${patchRes.status}: ${text.slice(0, 200)}`);
|
|
40012
39783
|
}
|
|
40013
|
-
const sendRes = await fetch(`${
|
|
39784
|
+
const sendRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}/send`, {
|
|
40014
39785
|
method: "POST",
|
|
40015
39786
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40016
39787
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40057,12 +39828,25 @@ function buildMessagePayload(args, idempotencyKey, cap) {
|
|
|
40057
39828
|
if (args.bcc?.length) {
|
|
40058
39829
|
payload.bccRecipients = args.bcc.map((address) => ({ emailAddress: { address } }));
|
|
40059
39830
|
}
|
|
39831
|
+
if (args.attachments?.length) {
|
|
39832
|
+
payload.attachments = args.attachments.map((a) => {
|
|
39833
|
+
if (!a?.name) throw new Error(`outlook-mail ${cap}: attachment \`name\` is required`);
|
|
39834
|
+
if (!a?.contentBytes) throw new Error(`outlook-mail ${cap}: attachment \`contentBytes\` (base64) is required`);
|
|
39835
|
+
const att = {
|
|
39836
|
+
"@odata.type": "#microsoft.graph.fileAttachment",
|
|
39837
|
+
name: a.name,
|
|
39838
|
+
contentBytes: a.contentBytes
|
|
39839
|
+
};
|
|
39840
|
+
if (a.contentType) att.contentType = a.contentType;
|
|
39841
|
+
return att;
|
|
39842
|
+
});
|
|
39843
|
+
}
|
|
40060
39844
|
return payload;
|
|
40061
39845
|
}
|
|
40062
39846
|
async function sendMessage(inv, accessToken, timeoutMs) {
|
|
40063
39847
|
const args = inv.args ?? {};
|
|
40064
39848
|
const message = buildMessagePayload(args, inv.idempotencyKey, "send_message");
|
|
40065
|
-
const res = await fetch(`${
|
|
39849
|
+
const res = await fetch(`${API12}/me/sendMail`, {
|
|
40066
39850
|
method: "POST",
|
|
40067
39851
|
headers: {
|
|
40068
39852
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40092,7 +39876,7 @@ async function sendMessage(inv, accessToken, timeoutMs) {
|
|
|
40092
39876
|
async function createDraft(inv, accessToken, timeoutMs) {
|
|
40093
39877
|
const args = inv.args ?? {};
|
|
40094
39878
|
const message = buildMessagePayload(args, inv.idempotencyKey, "create_draft");
|
|
40095
|
-
const res = await fetch(`${
|
|
39879
|
+
const res = await fetch(`${API12}/me/messages`, {
|
|
40096
39880
|
method: "POST",
|
|
40097
39881
|
headers: {
|
|
40098
39882
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40133,7 +39917,7 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40133
39917
|
expirationDateTime,
|
|
40134
39918
|
clientState: clientState ?? inv.idempotencyKey
|
|
40135
39919
|
};
|
|
40136
|
-
const res = await fetch(`${
|
|
39920
|
+
const res = await fetch(`${API12}/subscriptions`, {
|
|
40137
39921
|
method: "POST",
|
|
40138
39922
|
headers: {
|
|
40139
39923
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40162,6 +39946,162 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40162
39946
|
idempotentReplay: false
|
|
40163
39947
|
};
|
|
40164
39948
|
}
|
|
39949
|
+
async function forwardMessage(inv, accessToken, timeoutMs) {
|
|
39950
|
+
const { messageId, to, comment } = inv.args;
|
|
39951
|
+
if (!messageId) throw new Error("outlook-mail forward_message: `messageId` is required");
|
|
39952
|
+
if (!to || Array.isArray(to) && to.length === 0) {
|
|
39953
|
+
throw new Error("outlook-mail forward_message: `to` is required");
|
|
39954
|
+
}
|
|
39955
|
+
const toList = Array.isArray(to) ? to : [to];
|
|
39956
|
+
const toRecipients = toList.map((address) => ({ emailAddress: { address } }));
|
|
39957
|
+
const fwdBody = {
|
|
39958
|
+
toRecipients
|
|
39959
|
+
};
|
|
39960
|
+
if (comment !== void 0) fwdBody.comment = comment;
|
|
39961
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/forward`, {
|
|
39962
|
+
method: "POST",
|
|
39963
|
+
headers: {
|
|
39964
|
+
authorization: `Bearer ${accessToken}`,
|
|
39965
|
+
"content-type": "application/json"
|
|
39966
|
+
},
|
|
39967
|
+
body: JSON.stringify(fwdBody),
|
|
39968
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
39969
|
+
});
|
|
39970
|
+
if (res.status === 401 || res.status === 403) {
|
|
39971
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
39972
|
+
}
|
|
39973
|
+
if (!res.ok && res.status !== 202) {
|
|
39974
|
+
const text = await res.text().catch(() => "");
|
|
39975
|
+
throw new Error(`outlook-mail forward_message ${res.status}: ${text.slice(0, 200)}`);
|
|
39976
|
+
}
|
|
39977
|
+
return {
|
|
39978
|
+
status: "committed",
|
|
39979
|
+
data: { forwarded: true, messageId, to: toList },
|
|
39980
|
+
committedAt: Date.now(),
|
|
39981
|
+
idempotentReplay: false
|
|
39982
|
+
};
|
|
39983
|
+
}
|
|
39984
|
+
async function moveMessage(inv, accessToken, timeoutMs) {
|
|
39985
|
+
const { messageId, destinationId } = inv.args;
|
|
39986
|
+
if (!messageId) throw new Error("outlook-mail move_message: `messageId` is required");
|
|
39987
|
+
if (!destinationId) throw new Error("outlook-mail move_message: `destinationId` is required");
|
|
39988
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/move`, {
|
|
39989
|
+
method: "POST",
|
|
39990
|
+
headers: {
|
|
39991
|
+
authorization: `Bearer ${accessToken}`,
|
|
39992
|
+
"content-type": "application/json"
|
|
39993
|
+
},
|
|
39994
|
+
body: JSON.stringify({ destinationId }),
|
|
39995
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
39996
|
+
});
|
|
39997
|
+
if (res.status === 401 || res.status === 403) {
|
|
39998
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
39999
|
+
}
|
|
40000
|
+
if (!res.ok) {
|
|
40001
|
+
const text = await res.text().catch(() => "");
|
|
40002
|
+
throw new Error(`outlook-mail move_message ${res.status}: ${text.slice(0, 200)}`);
|
|
40003
|
+
}
|
|
40004
|
+
const json = await res.json().catch(() => ({}));
|
|
40005
|
+
return {
|
|
40006
|
+
status: "committed",
|
|
40007
|
+
data: {
|
|
40008
|
+
moved: true,
|
|
40009
|
+
messageId: json.id ?? messageId,
|
|
40010
|
+
parentFolderId: json.parentFolderId ?? destinationId,
|
|
40011
|
+
destinationId
|
|
40012
|
+
},
|
|
40013
|
+
committedAt: Date.now(),
|
|
40014
|
+
idempotentReplay: false
|
|
40015
|
+
};
|
|
40016
|
+
}
|
|
40017
|
+
async function setLabels(inv, accessToken, timeoutMs) {
|
|
40018
|
+
const { messageId, categories } = inv.args;
|
|
40019
|
+
if (!messageId) throw new Error("outlook-mail set_labels: `messageId` is required");
|
|
40020
|
+
if (!Array.isArray(categories)) {
|
|
40021
|
+
throw new Error("outlook-mail set_labels: `categories` must be an array (the full desired set)");
|
|
40022
|
+
}
|
|
40023
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}`, {
|
|
40024
|
+
method: "PATCH",
|
|
40025
|
+
headers: {
|
|
40026
|
+
authorization: `Bearer ${accessToken}`,
|
|
40027
|
+
"content-type": "application/json"
|
|
40028
|
+
},
|
|
40029
|
+
body: JSON.stringify({ categories }),
|
|
40030
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40031
|
+
});
|
|
40032
|
+
if (res.status === 401 || res.status === 403) {
|
|
40033
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40034
|
+
}
|
|
40035
|
+
if (!res.ok) {
|
|
40036
|
+
const text = await res.text().catch(() => "");
|
|
40037
|
+
throw new Error(`outlook-mail set_labels ${res.status}: ${text.slice(0, 200)}`);
|
|
40038
|
+
}
|
|
40039
|
+
const json = await res.json().catch(() => ({}));
|
|
40040
|
+
return {
|
|
40041
|
+
status: "committed",
|
|
40042
|
+
data: {
|
|
40043
|
+
messageId: json.id ?? messageId,
|
|
40044
|
+
categories: json.categories ?? categories
|
|
40045
|
+
},
|
|
40046
|
+
committedAt: Date.now(),
|
|
40047
|
+
idempotentReplay: false
|
|
40048
|
+
};
|
|
40049
|
+
}
|
|
40050
|
+
async function sendDraft(inv, accessToken, timeoutMs) {
|
|
40051
|
+
const { messageId } = inv.args;
|
|
40052
|
+
if (!messageId) throw new Error("outlook-mail send_draft: `messageId` is required");
|
|
40053
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/send`, {
|
|
40054
|
+
method: "POST",
|
|
40055
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
40056
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40057
|
+
});
|
|
40058
|
+
if (res.status === 401 || res.status === 403) {
|
|
40059
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40060
|
+
}
|
|
40061
|
+
if (!res.ok && res.status !== 202) {
|
|
40062
|
+
const text = await res.text().catch(() => "");
|
|
40063
|
+
throw new Error(`outlook-mail send_draft ${res.status}: ${text.slice(0, 200)}`);
|
|
40064
|
+
}
|
|
40065
|
+
return {
|
|
40066
|
+
status: "committed",
|
|
40067
|
+
data: { sent: true, messageId },
|
|
40068
|
+
committedAt: Date.now(),
|
|
40069
|
+
idempotentReplay: false
|
|
40070
|
+
};
|
|
40071
|
+
}
|
|
40072
|
+
async function downloadAttachment(inv, accessToken, timeoutMs) {
|
|
40073
|
+
const { messageId, attachmentId } = inv.args;
|
|
40074
|
+
const url = `${API12}/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`;
|
|
40075
|
+
const res = await fetch(url, {
|
|
40076
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
40077
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40078
|
+
});
|
|
40079
|
+
if (res.status === 401 || res.status === 403) {
|
|
40080
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40081
|
+
}
|
|
40082
|
+
if (res.status === 404) {
|
|
40083
|
+
throw new Error(`outlook-mail download_attachment: attachment ${attachmentId} on message ${messageId} not found`);
|
|
40084
|
+
}
|
|
40085
|
+
if (!res.ok) {
|
|
40086
|
+
const text = await res.text().catch(() => "");
|
|
40087
|
+
throw new Error(`outlook-mail download_attachment ${res.status}: ${text.slice(0, 200)}`);
|
|
40088
|
+
}
|
|
40089
|
+
const a = await res.json();
|
|
40090
|
+
return {
|
|
40091
|
+
data: {
|
|
40092
|
+
id: a.id ?? attachmentId,
|
|
40093
|
+
name: a.name ?? "",
|
|
40094
|
+
contentType: a.contentType ?? "application/octet-stream",
|
|
40095
|
+
size: a.size ?? 0,
|
|
40096
|
+
isInline: a.isInline ?? false,
|
|
40097
|
+
attachmentType: a["@odata.type"],
|
|
40098
|
+
// Base64 bytes for file attachments; null for item/reference attachments
|
|
40099
|
+
// which carry no inline contentBytes.
|
|
40100
|
+
contentBytes: a.contentBytes ?? null
|
|
40101
|
+
},
|
|
40102
|
+
fetchedAt: Date.now()
|
|
40103
|
+
};
|
|
40104
|
+
}
|
|
40165
40105
|
async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredentialsRotated) {
|
|
40166
40106
|
if (creds.kind !== "oauth2") {
|
|
40167
40107
|
throw new Error("outlook-mail: expected oauth2 credentials");
|
|
@@ -40173,7 +40113,7 @@ async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredent
|
|
|
40173
40113
|
throw new CredentialsExpired("Outlook Mail access token expired and no refresh token", "");
|
|
40174
40114
|
}
|
|
40175
40115
|
const refreshed = await refreshAccessToken({
|
|
40176
|
-
tokenUrl:
|
|
40116
|
+
tokenUrl: TOKEN_URL14,
|
|
40177
40117
|
clientId,
|
|
40178
40118
|
clientSecret,
|
|
40179
40119
|
refreshToken: creds.refreshToken
|
|
@@ -40201,8 +40141,8 @@ var SCOPES12 = [
|
|
|
40201
40141
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
40202
40142
|
"offline_access"
|
|
40203
40143
|
];
|
|
40204
|
-
var
|
|
40205
|
-
var
|
|
40144
|
+
var AUTH_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
40145
|
+
var TOKEN_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
40206
40146
|
var GRAPH2 = "https://graph.microsoft.com/v1.0";
|
|
40207
40147
|
function microsoftTeams(opts) {
|
|
40208
40148
|
const { clientId, clientSecret } = opts;
|
|
@@ -40213,8 +40153,8 @@ function microsoftTeams(opts) {
|
|
|
40213
40153
|
description: "Post messages from the agent into Microsoft Teams channels and 1:1/group chats, list teams and channels, and look up users by email. Advisory surface \u2014 Teams posts are informational, not transactional.",
|
|
40214
40154
|
auth: {
|
|
40215
40155
|
kind: "oauth2",
|
|
40216
|
-
authorizationUrl:
|
|
40217
|
-
tokenUrl:
|
|
40156
|
+
authorizationUrl: AUTH_URL15,
|
|
40157
|
+
tokenUrl: TOKEN_URL15,
|
|
40218
40158
|
scopes: SCOPES12,
|
|
40219
40159
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40220
40160
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40400,7 +40340,7 @@ function microsoftTeams(opts) {
|
|
|
40400
40340
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40401
40341
|
}
|
|
40402
40342
|
const tokens = await exchangeAuthorizationCode({
|
|
40403
|
-
tokenUrl:
|
|
40343
|
+
tokenUrl: TOKEN_URL15,
|
|
40404
40344
|
clientId,
|
|
40405
40345
|
clientSecret,
|
|
40406
40346
|
code: input.code,
|
|
@@ -40423,7 +40363,7 @@ function microsoftTeams(opts) {
|
|
|
40423
40363
|
throw new Error("microsoft-teams.refreshToken: missing refresh token");
|
|
40424
40364
|
}
|
|
40425
40365
|
const refreshed = await refreshAccessToken({
|
|
40426
|
-
tokenUrl:
|
|
40366
|
+
tokenUrl: TOKEN_URL15,
|
|
40427
40367
|
clientId,
|
|
40428
40368
|
clientSecret,
|
|
40429
40369
|
refreshToken: creds.refreshToken
|
|
@@ -40465,7 +40405,7 @@ async function ensureFreshAccessToken13(creds, clientId, clientSecret) {
|
|
|
40465
40405
|
throw new CredentialsExpired("Microsoft Teams access token expired and no refresh token", "");
|
|
40466
40406
|
}
|
|
40467
40407
|
const refreshed = await refreshAccessToken({
|
|
40468
|
-
tokenUrl:
|
|
40408
|
+
tokenUrl: TOKEN_URL15,
|
|
40469
40409
|
clientId,
|
|
40470
40410
|
clientSecret,
|
|
40471
40411
|
refreshToken: creds.refreshToken
|
|
@@ -40517,9 +40457,9 @@ function escapeOData2(value) {
|
|
|
40517
40457
|
var SCOPE_READ3 = "https://graph.microsoft.com/Files.Read";
|
|
40518
40458
|
var SCOPE_WRITE4 = "https://graph.microsoft.com/Files.ReadWrite";
|
|
40519
40459
|
var SCOPE_OFFLINE2 = "offline_access";
|
|
40520
|
-
var
|
|
40521
|
-
var
|
|
40522
|
-
var
|
|
40460
|
+
var AUTH_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
40461
|
+
var TOKEN_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
40462
|
+
var API13 = "https://graph.microsoft.com/v1.0";
|
|
40523
40463
|
function oneDrive(opts) {
|
|
40524
40464
|
const { clientId, clientSecret } = opts;
|
|
40525
40465
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -40531,8 +40471,8 @@ function oneDrive(opts) {
|
|
|
40531
40471
|
description: "Read and watch files in the user's OneDrive. List a folder, fetch a document's contents (Word/Excel/PowerPoint/PDF/images), and subscribe to folder change notifications via Graph subscriptions.",
|
|
40532
40472
|
auth: {
|
|
40533
40473
|
kind: "oauth2",
|
|
40534
|
-
authorizationUrl:
|
|
40535
|
-
tokenUrl:
|
|
40474
|
+
authorizationUrl: AUTH_URL16,
|
|
40475
|
+
tokenUrl: TOKEN_URL16,
|
|
40536
40476
|
scopes,
|
|
40537
40477
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40538
40478
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40709,7 +40649,7 @@ function oneDrive(opts) {
|
|
|
40709
40649
|
throw new Error("OneDrive OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40710
40650
|
}
|
|
40711
40651
|
const tokens = await exchangeAuthorizationCode({
|
|
40712
|
-
tokenUrl:
|
|
40652
|
+
tokenUrl: TOKEN_URL16,
|
|
40713
40653
|
clientId,
|
|
40714
40654
|
clientSecret,
|
|
40715
40655
|
code: input.code,
|
|
@@ -40732,7 +40672,7 @@ function oneDrive(opts) {
|
|
|
40732
40672
|
throw new Error("onedrive.refreshToken: missing refresh token");
|
|
40733
40673
|
}
|
|
40734
40674
|
const refreshed = await refreshAccessToken({
|
|
40735
|
-
tokenUrl:
|
|
40675
|
+
tokenUrl: TOKEN_URL16,
|
|
40736
40676
|
clientId,
|
|
40737
40677
|
clientSecret,
|
|
40738
40678
|
refreshToken: creds.refreshToken
|
|
@@ -40747,7 +40687,7 @@ function oneDrive(opts) {
|
|
|
40747
40687
|
async test(source) {
|
|
40748
40688
|
try {
|
|
40749
40689
|
const accessToken = await ensureFreshAccessToken14(source.credentials, clientId, clientSecret);
|
|
40750
|
-
const res = await fetch(`${
|
|
40690
|
+
const res = await fetch(`${API13}/me/drive?$select=id`, {
|
|
40751
40691
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40752
40692
|
signal: AbortSignal.timeout(8e3)
|
|
40753
40693
|
});
|
|
@@ -40776,7 +40716,7 @@ async function listFiles2(inv, accessToken, timeoutMs) {
|
|
|
40776
40716
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
40777
40717
|
const path = args.folderId ? `/me/drive/items/${encodeURIComponent(args.folderId)}/children` : "/me/drive/root/children";
|
|
40778
40718
|
const useSearchEndpoint = !!args.query && !args.folderId;
|
|
40779
|
-
const url = useSearchEndpoint ? `${
|
|
40719
|
+
const url = useSearchEndpoint ? `${API13}/me/drive/root/search(q=${encodeURIComponent(`'${args.query.replace(/'/g, "''")}'`)})?${stripSearch(params).toString()}` : `${API13}${path}?${params.toString()}`;
|
|
40780
40720
|
const res = await fetch(url, {
|
|
40781
40721
|
headers,
|
|
40782
40722
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40806,7 +40746,7 @@ function stripSearch(params) {
|
|
|
40806
40746
|
async function readFile2(inv, accessToken, timeoutMs) {
|
|
40807
40747
|
const { fileId } = inv.args ?? {};
|
|
40808
40748
|
if (!fileId) throw new Error("onedrive read_file: fileId is required");
|
|
40809
|
-
const metaUrl = `${
|
|
40749
|
+
const metaUrl = `${API13}/me/drive/items/${encodeURIComponent(fileId)}?$select=id,name,eTag,lastModifiedDateTime,size,file,folder`;
|
|
40810
40750
|
const metaRes = await fetch(metaUrl, {
|
|
40811
40751
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40812
40752
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40827,7 +40767,7 @@ async function readFile2(inv, accessToken, timeoutMs) {
|
|
|
40827
40767
|
}
|
|
40828
40768
|
const mimeType = meta.file?.mimeType ?? "application/octet-stream";
|
|
40829
40769
|
const fetchedAt = Date.now();
|
|
40830
|
-
const contentRes = await fetch(`${
|
|
40770
|
+
const contentRes = await fetch(`${API13}/me/drive/items/${encodeURIComponent(fileId)}/content`, {
|
|
40831
40771
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40832
40772
|
signal: AbortSignal.timeout(timeoutMs)
|
|
40833
40773
|
});
|
|
@@ -40880,7 +40820,7 @@ async function watchFolder2(inv, accessToken, timeoutMs) {
|
|
|
40880
40820
|
expirationDateTime,
|
|
40881
40821
|
clientState: clientState ?? inv.idempotencyKey
|
|
40882
40822
|
};
|
|
40883
|
-
const res = await fetch(`${
|
|
40823
|
+
const res = await fetch(`${API13}/subscriptions`, {
|
|
40884
40824
|
method: "POST",
|
|
40885
40825
|
headers: {
|
|
40886
40826
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40920,7 +40860,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40920
40860
|
}
|
|
40921
40861
|
const body = encoding === "base64" ? Buffer.from(fileContent, "base64") : Buffer.from(fileContent, "utf-8");
|
|
40922
40862
|
const parentSegment = folderId === "root" ? "/me/drive/root" : `/me/drive/items/${encodeURIComponent(folderId)}`;
|
|
40923
|
-
const url = `${
|
|
40863
|
+
const url = `${API13}${parentSegment}:/${encodeURIComponent(fileName)}:/content`;
|
|
40924
40864
|
const res = await fetch(url, {
|
|
40925
40865
|
method: "PUT",
|
|
40926
40866
|
headers: {
|
|
@@ -40956,7 +40896,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40956
40896
|
async function deleteItem(inv, accessToken, timeoutMs) {
|
|
40957
40897
|
const { itemId } = inv.args ?? {};
|
|
40958
40898
|
if (!itemId) throw new Error("onedrive files.delete: itemId is required");
|
|
40959
|
-
const res = await fetch(`${
|
|
40899
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40960
40900
|
method: "DELETE",
|
|
40961
40901
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40962
40902
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40994,7 +40934,7 @@ async function moveItem(inv, accessToken, timeoutMs) {
|
|
|
40994
40934
|
body.parentReference = newParentId === "root" ? { path: "/drive/root" } : { id: newParentId };
|
|
40995
40935
|
}
|
|
40996
40936
|
if (newName) body.name = newName;
|
|
40997
|
-
const res = await fetch(`${
|
|
40937
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40998
40938
|
method: "PATCH",
|
|
40999
40939
|
headers: {
|
|
41000
40940
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41034,7 +40974,7 @@ async function shareItem(inv, accessToken, timeoutMs) {
|
|
|
41034
40974
|
};
|
|
41035
40975
|
if (password) body.password = password;
|
|
41036
40976
|
if (expirationDateTime) body.expirationDateTime = expirationDateTime;
|
|
41037
|
-
const res = await fetch(`${
|
|
40977
|
+
const res = await fetch(`${API13}${itemPath(itemId)}/createLink`, {
|
|
41038
40978
|
method: "POST",
|
|
41039
40979
|
headers: {
|
|
41040
40980
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41073,7 +41013,7 @@ async function createFolder2(inv, accessToken, timeoutMs) {
|
|
|
41073
41013
|
folder: {},
|
|
41074
41014
|
"@microsoft.graph.conflictBehavior": conflictBehavior ?? "fail"
|
|
41075
41015
|
};
|
|
41076
|
-
const res = await fetch(`${
|
|
41016
|
+
const res = await fetch(`${API13}${parentSegment}`, {
|
|
41077
41017
|
method: "POST",
|
|
41078
41018
|
headers: {
|
|
41079
41019
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41115,7 +41055,7 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41115
41055
|
throw new CredentialsExpired("OneDrive access token expired and no refresh token", "");
|
|
41116
41056
|
}
|
|
41117
41057
|
const refreshed = await refreshAccessToken({
|
|
41118
|
-
tokenUrl:
|
|
41058
|
+
tokenUrl: TOKEN_URL16,
|
|
41119
41059
|
clientId,
|
|
41120
41060
|
clientSecret,
|
|
41121
41061
|
refreshToken: creds.refreshToken
|
|
@@ -41134,13 +41074,13 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41134
41074
|
|
|
41135
41075
|
// src/connectors/adapters/sharepoint.ts
|
|
41136
41076
|
var SCOPES13 = [
|
|
41137
|
-
"https://graph.microsoft.com/Sites.
|
|
41077
|
+
"https://graph.microsoft.com/Sites.ReadWrite.All",
|
|
41138
41078
|
"https://graph.microsoft.com/Files.ReadWrite.All",
|
|
41139
41079
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
41140
41080
|
"offline_access"
|
|
41141
41081
|
];
|
|
41142
|
-
var
|
|
41143
|
-
var
|
|
41082
|
+
var AUTH_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
41083
|
+
var TOKEN_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
41144
41084
|
var GRAPH3 = "https://graph.microsoft.com/v1.0";
|
|
41145
41085
|
var MAX_INLINE_BYTES = 4 * 1024 * 1024;
|
|
41146
41086
|
function sharepoint(opts) {
|
|
@@ -41152,8 +41092,8 @@ function sharepoint(opts) {
|
|
|
41152
41092
|
description: "Let your agent discover SharePoint sites, list/search their document libraries, read small file contents, upload files, and create folders. Etag-CAS available on every DriveItem for follow-up patch/delete flows.",
|
|
41153
41093
|
auth: {
|
|
41154
41094
|
kind: "oauth2",
|
|
41155
|
-
authorizationUrl:
|
|
41156
|
-
tokenUrl:
|
|
41095
|
+
authorizationUrl: AUTH_URL17,
|
|
41096
|
+
tokenUrl: TOKEN_URL17,
|
|
41157
41097
|
scopes: SCOPES13,
|
|
41158
41098
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
41159
41099
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -41356,6 +41296,136 @@ function sharepoint(opts) {
|
|
|
41356
41296
|
},
|
|
41357
41297
|
required: ["siteId", "listId", "fields"]
|
|
41358
41298
|
}
|
|
41299
|
+
},
|
|
41300
|
+
{
|
|
41301
|
+
name: "get_site_info",
|
|
41302
|
+
class: "read",
|
|
41303
|
+
description: "Read the metadata for a SharePoint site by site id (id, name, displayName, webUrl, description).",
|
|
41304
|
+
parameters: {
|
|
41305
|
+
type: "object",
|
|
41306
|
+
properties: {
|
|
41307
|
+
siteId: { type: "string", description: 'Graph site id (composite "host,site-id,web-id").' }
|
|
41308
|
+
},
|
|
41309
|
+
required: ["siteId"]
|
|
41310
|
+
}
|
|
41311
|
+
},
|
|
41312
|
+
{
|
|
41313
|
+
name: "lists.items.find",
|
|
41314
|
+
class: "read",
|
|
41315
|
+
description: "List items in a SharePoint list, optionally filtered with $filter and shaped with $expand (e.g. fields($select=...)).",
|
|
41316
|
+
parameters: {
|
|
41317
|
+
type: "object",
|
|
41318
|
+
properties: {
|
|
41319
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41320
|
+
listId: { type: "string", description: "SharePoint list id (or list display name resolved by the caller)." },
|
|
41321
|
+
filter: { type: "string", description: "Optional OData $filter expression." },
|
|
41322
|
+
expand: { type: "string", description: "Optional OData $expand, e.g. fields($select=Title,Status)." },
|
|
41323
|
+
top: { type: "integer", minimum: 1, maximum: 200, default: 50 }
|
|
41324
|
+
},
|
|
41325
|
+
required: ["siteId", "listId"]
|
|
41326
|
+
}
|
|
41327
|
+
},
|
|
41328
|
+
{
|
|
41329
|
+
name: "copy_item",
|
|
41330
|
+
class: "mutation",
|
|
41331
|
+
description: "Copy a file or folder DriveItem. Graph copy is asynchronous \u2014 it returns 202 Accepted with a Location monitor URL rather than the new DriveItem. Supply either a cross-drive parentReference (driveId + id) or a same-site target parent id via targetParentId; optionally rename via name.",
|
|
41332
|
+
cas: "native-idempotency",
|
|
41333
|
+
externalEffect: true,
|
|
41334
|
+
parameters: {
|
|
41335
|
+
type: "object",
|
|
41336
|
+
properties: {
|
|
41337
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41338
|
+
itemId: { type: "string", description: "DriveItem id of the file or folder to copy." },
|
|
41339
|
+
parentReference: {
|
|
41340
|
+
type: "object",
|
|
41341
|
+
description: "Cross-drive destination reference (driveId + id). Provide this OR targetParentId.",
|
|
41342
|
+
additionalProperties: true
|
|
41343
|
+
},
|
|
41344
|
+
targetParentId: {
|
|
41345
|
+
type: "string",
|
|
41346
|
+
description: "Same-site destination parent folder DriveItem id. Provide this OR parentReference."
|
|
41347
|
+
},
|
|
41348
|
+
name: { type: "string", description: "Optional new name for the copied item." }
|
|
41349
|
+
},
|
|
41350
|
+
required: ["siteId", "itemId"]
|
|
41351
|
+
}
|
|
41352
|
+
},
|
|
41353
|
+
{
|
|
41354
|
+
name: "lists.create",
|
|
41355
|
+
class: "mutation",
|
|
41356
|
+
description: "Create a SharePoint list on the site. displayName is required; columns and list (e.g. { template }) are optional.",
|
|
41357
|
+
cas: "native-idempotency",
|
|
41358
|
+
externalEffect: true,
|
|
41359
|
+
parameters: {
|
|
41360
|
+
type: "object",
|
|
41361
|
+
properties: {
|
|
41362
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41363
|
+
displayName: { type: "string", description: "Display name of the new list." },
|
|
41364
|
+
columns: {
|
|
41365
|
+
type: "array",
|
|
41366
|
+
description: "Optional column definitions for the list.",
|
|
41367
|
+
items: { type: "object", additionalProperties: true }
|
|
41368
|
+
},
|
|
41369
|
+
list: {
|
|
41370
|
+
type: "object",
|
|
41371
|
+
description: 'Optional list facet, e.g. { template: "genericList" }.',
|
|
41372
|
+
additionalProperties: true
|
|
41373
|
+
}
|
|
41374
|
+
},
|
|
41375
|
+
required: ["siteId", "displayName"]
|
|
41376
|
+
}
|
|
41377
|
+
},
|
|
41378
|
+
{
|
|
41379
|
+
name: "lists.items.update",
|
|
41380
|
+
class: "mutation",
|
|
41381
|
+
description: "Patch the fields on an existing list item. Supports etag-CAS via If-Match \u2014 pass the item's etag to guard against concurrent writes; a mismatch surfaces as ResourceContention.",
|
|
41382
|
+
cas: "etag-if-match",
|
|
41383
|
+
externalEffect: true,
|
|
41384
|
+
parameters: {
|
|
41385
|
+
type: "object",
|
|
41386
|
+
properties: {
|
|
41387
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41388
|
+
listId: { type: "string", description: "SharePoint list id." },
|
|
41389
|
+
itemId: { type: "string", description: "List item id to update." },
|
|
41390
|
+
fields: {
|
|
41391
|
+
type: "object",
|
|
41392
|
+
description: "Map of column internal-name \u2192 new value.",
|
|
41393
|
+
additionalProperties: true
|
|
41394
|
+
}
|
|
41395
|
+
},
|
|
41396
|
+
required: ["siteId", "listId", "itemId", "fields"]
|
|
41397
|
+
}
|
|
41398
|
+
},
|
|
41399
|
+
{
|
|
41400
|
+
name: "lists.items.delete",
|
|
41401
|
+
class: "mutation",
|
|
41402
|
+
description: "Delete a list item by id. Graph returns 204 on success. (siteId, listId, itemId) is the natural idempotency tuple \u2014 a re-delete of a missing item surfaces as 404 mapped to a tombstone result.",
|
|
41403
|
+
cas: "native-idempotency",
|
|
41404
|
+
externalEffect: true,
|
|
41405
|
+
parameters: {
|
|
41406
|
+
type: "object",
|
|
41407
|
+
properties: {
|
|
41408
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41409
|
+
listId: { type: "string", description: "SharePoint list id." },
|
|
41410
|
+
itemId: { type: "string", description: "List item id to delete." }
|
|
41411
|
+
},
|
|
41412
|
+
required: ["siteId", "listId", "itemId"]
|
|
41413
|
+
}
|
|
41414
|
+
},
|
|
41415
|
+
{
|
|
41416
|
+
name: "pages.publish",
|
|
41417
|
+
class: "mutation",
|
|
41418
|
+
description: "Publish a SharePoint site page by page id.",
|
|
41419
|
+
cas: "native-idempotency",
|
|
41420
|
+
externalEffect: true,
|
|
41421
|
+
parameters: {
|
|
41422
|
+
type: "object",
|
|
41423
|
+
properties: {
|
|
41424
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41425
|
+
pageId: { type: "string", description: "Site page id to publish." }
|
|
41426
|
+
},
|
|
41427
|
+
required: ["siteId", "pageId"]
|
|
41428
|
+
}
|
|
41359
41429
|
}
|
|
41360
41430
|
]
|
|
41361
41431
|
},
|
|
@@ -41505,6 +41575,41 @@ function sharepoint(opts) {
|
|
|
41505
41575
|
fetchedAt: Date.now()
|
|
41506
41576
|
};
|
|
41507
41577
|
}
|
|
41578
|
+
if (inv.capabilityName === "get_site_info") {
|
|
41579
|
+
const { siteId } = inv.args;
|
|
41580
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}?$select=id,name,displayName,webUrl,description`;
|
|
41581
|
+
const site = await graphGet4(url, accessToken, inv.source.id);
|
|
41582
|
+
return {
|
|
41583
|
+
data: {
|
|
41584
|
+
id: site.id,
|
|
41585
|
+
name: site.displayName ?? site.name,
|
|
41586
|
+
webUrl: site.webUrl,
|
|
41587
|
+
description: site.description
|
|
41588
|
+
},
|
|
41589
|
+
fetchedAt: Date.now()
|
|
41590
|
+
};
|
|
41591
|
+
}
|
|
41592
|
+
if (inv.capabilityName === "lists.items.find") {
|
|
41593
|
+
const { siteId, listId, filter, expand, top } = inv.args;
|
|
41594
|
+
const t = clamp(top ?? 50, 1, 200);
|
|
41595
|
+
const params = new URLSearchParams();
|
|
41596
|
+
params.set("$top", String(t));
|
|
41597
|
+
if (typeof filter === "string" && filter.length > 0) params.set("$filter", filter);
|
|
41598
|
+
if (typeof expand === "string" && expand.length > 0) params.set("$expand", expand);
|
|
41599
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items?${params.toString()}`;
|
|
41600
|
+
const json = await graphGet4(url, accessToken, inv.source.id);
|
|
41601
|
+
const items = (json.value ?? []).map((it) => ({
|
|
41602
|
+
id: it.id,
|
|
41603
|
+
webUrl: it.webUrl,
|
|
41604
|
+
etag: it.eTag,
|
|
41605
|
+
lastModifiedAt: it.lastModifiedDateTime,
|
|
41606
|
+
fields: it.fields
|
|
41607
|
+
}));
|
|
41608
|
+
return {
|
|
41609
|
+
data: { items, nextLink: json["@odata.nextLink"] },
|
|
41610
|
+
fetchedAt: Date.now()
|
|
41611
|
+
};
|
|
41612
|
+
}
|
|
41508
41613
|
throw new Error(`sharepoint: unknown read capability ${inv.capabilityName}`);
|
|
41509
41614
|
},
|
|
41510
41615
|
async executeMutation(inv) {
|
|
@@ -41814,6 +41919,211 @@ function sharepoint(opts) {
|
|
|
41814
41919
|
idempotentReplay: false
|
|
41815
41920
|
};
|
|
41816
41921
|
}
|
|
41922
|
+
if (inv.capabilityName === "copy_item") {
|
|
41923
|
+
const { siteId, itemId, parentReference, targetParentId, name } = inv.args;
|
|
41924
|
+
const ref = parentReference && Object.keys(parentReference).length > 0 ? parentReference : typeof targetParentId === "string" && targetParentId.length > 0 ? { id: targetParentId } : void 0;
|
|
41925
|
+
if (!ref) {
|
|
41926
|
+
throw new Error(
|
|
41927
|
+
"sharepoint copy_item: provide either parentReference (cross-drive) or targetParentId (same-site)"
|
|
41928
|
+
);
|
|
41929
|
+
}
|
|
41930
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/drive/items/${encodeURIComponent(itemId)}/copy`;
|
|
41931
|
+
const body = { parentReference: ref };
|
|
41932
|
+
if (typeof name === "string" && name.length > 0) body.name = name;
|
|
41933
|
+
const res = await fetch(url, {
|
|
41934
|
+
method: "POST",
|
|
41935
|
+
headers: {
|
|
41936
|
+
authorization: `Bearer ${accessToken}`,
|
|
41937
|
+
"content-type": "application/json",
|
|
41938
|
+
accept: "application/json"
|
|
41939
|
+
},
|
|
41940
|
+
body: JSON.stringify(body),
|
|
41941
|
+
signal: AbortSignal.timeout(15e3)
|
|
41942
|
+
});
|
|
41943
|
+
if (res.status === 401 || res.status === 403) {
|
|
41944
|
+
throw new CredentialsExpired(
|
|
41945
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
41946
|
+
inv.source.id
|
|
41947
|
+
);
|
|
41948
|
+
}
|
|
41949
|
+
if (res.status === 409 || res.status === 412) {
|
|
41950
|
+
throw new ResourceContention(
|
|
41951
|
+
`Microsoft Graph reported conflict on copy_item (${res.status})`,
|
|
41952
|
+
[]
|
|
41953
|
+
);
|
|
41954
|
+
}
|
|
41955
|
+
if (!res.ok && res.status !== 202) {
|
|
41956
|
+
const text = await res.text().catch(() => "");
|
|
41957
|
+
throw new Error(`sharepoint copy_item ${res.status}: ${text.slice(0, 200)}`);
|
|
41958
|
+
}
|
|
41959
|
+
const monitorUrl = res.headers.get("location") ?? void 0;
|
|
41960
|
+
return {
|
|
41961
|
+
status: "committed",
|
|
41962
|
+
data: { id: itemId, accepted: true, async: true, monitorUrl },
|
|
41963
|
+
committedAt: Date.now(),
|
|
41964
|
+
idempotentReplay: false
|
|
41965
|
+
};
|
|
41966
|
+
}
|
|
41967
|
+
if (inv.capabilityName === "lists.create") {
|
|
41968
|
+
const { siteId, displayName, columns, list } = inv.args;
|
|
41969
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists`;
|
|
41970
|
+
const body = { displayName };
|
|
41971
|
+
if (Array.isArray(columns)) body.columns = columns;
|
|
41972
|
+
if (list && typeof list === "object") body.list = list;
|
|
41973
|
+
const res = await fetch(url, {
|
|
41974
|
+
method: "POST",
|
|
41975
|
+
headers: {
|
|
41976
|
+
authorization: `Bearer ${accessToken}`,
|
|
41977
|
+
"content-type": "application/json",
|
|
41978
|
+
accept: "application/json"
|
|
41979
|
+
},
|
|
41980
|
+
body: JSON.stringify(body),
|
|
41981
|
+
signal: AbortSignal.timeout(15e3)
|
|
41982
|
+
});
|
|
41983
|
+
if (res.status === 401 || res.status === 403) {
|
|
41984
|
+
throw new CredentialsExpired(
|
|
41985
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
41986
|
+
inv.source.id
|
|
41987
|
+
);
|
|
41988
|
+
}
|
|
41989
|
+
if (res.status === 409 || res.status === 412) {
|
|
41990
|
+
throw new ResourceContention(
|
|
41991
|
+
`Microsoft Graph reported conflict on lists.create (${res.status})`,
|
|
41992
|
+
[]
|
|
41993
|
+
);
|
|
41994
|
+
}
|
|
41995
|
+
if (!res.ok) {
|
|
41996
|
+
const text = await res.text().catch(() => "");
|
|
41997
|
+
throw new Error(`sharepoint lists.create ${res.status}: ${text.slice(0, 200)}`);
|
|
41998
|
+
}
|
|
41999
|
+
const created = await res.json();
|
|
42000
|
+
return {
|
|
42001
|
+
status: "committed",
|
|
42002
|
+
data: {
|
|
42003
|
+
id: created.id,
|
|
42004
|
+
displayName: created.displayName ?? created.name,
|
|
42005
|
+
webUrl: created.webUrl
|
|
42006
|
+
},
|
|
42007
|
+
etagAfter: created["@odata.etag"] ?? created.eTag,
|
|
42008
|
+
committedAt: Date.now(),
|
|
42009
|
+
idempotentReplay: false
|
|
42010
|
+
};
|
|
42011
|
+
}
|
|
42012
|
+
if (inv.capabilityName === "lists.items.update") {
|
|
42013
|
+
const { siteId, listId, itemId, fields } = inv.args;
|
|
42014
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}/fields`;
|
|
42015
|
+
const headers = {
|
|
42016
|
+
authorization: `Bearer ${accessToken}`,
|
|
42017
|
+
"content-type": "application/json",
|
|
42018
|
+
accept: "application/json"
|
|
42019
|
+
};
|
|
42020
|
+
if (typeof inv.expectedEtag === "string" && inv.expectedEtag.length > 0) {
|
|
42021
|
+
headers["if-match"] = inv.expectedEtag;
|
|
42022
|
+
}
|
|
42023
|
+
const res = await fetch(url, {
|
|
42024
|
+
method: "PATCH",
|
|
42025
|
+
headers,
|
|
42026
|
+
body: JSON.stringify(fields),
|
|
42027
|
+
signal: AbortSignal.timeout(15e3)
|
|
42028
|
+
});
|
|
42029
|
+
if (res.status === 401 || res.status === 403) {
|
|
42030
|
+
throw new CredentialsExpired(
|
|
42031
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42032
|
+
inv.source.id
|
|
42033
|
+
);
|
|
42034
|
+
}
|
|
42035
|
+
if (res.status === 409 || res.status === 412) {
|
|
42036
|
+
throw new ResourceContention(
|
|
42037
|
+
`Microsoft Graph reported conflict on lists.items.update (${res.status})`,
|
|
42038
|
+
[]
|
|
42039
|
+
);
|
|
42040
|
+
}
|
|
42041
|
+
if (!res.ok) {
|
|
42042
|
+
const text = await res.text().catch(() => "");
|
|
42043
|
+
throw new Error(`sharepoint lists.items.update ${res.status}: ${text.slice(0, 200)}`);
|
|
42044
|
+
}
|
|
42045
|
+
const updated = await res.json();
|
|
42046
|
+
return {
|
|
42047
|
+
status: "committed",
|
|
42048
|
+
data: { id: itemId, fields: updated },
|
|
42049
|
+
etagAfter: updated["@odata.etag"] ?? updated.eTag,
|
|
42050
|
+
committedAt: Date.now(),
|
|
42051
|
+
idempotentReplay: false
|
|
42052
|
+
};
|
|
42053
|
+
}
|
|
42054
|
+
if (inv.capabilityName === "lists.items.delete") {
|
|
42055
|
+
const { siteId, listId, itemId } = inv.args;
|
|
42056
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}`;
|
|
42057
|
+
const res = await fetch(url, {
|
|
42058
|
+
method: "DELETE",
|
|
42059
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
42060
|
+
signal: AbortSignal.timeout(15e3)
|
|
42061
|
+
});
|
|
42062
|
+
if (res.status === 401 || res.status === 403) {
|
|
42063
|
+
throw new CredentialsExpired(
|
|
42064
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42065
|
+
inv.source.id
|
|
42066
|
+
);
|
|
42067
|
+
}
|
|
42068
|
+
if (res.status === 412 || res.status === 409) {
|
|
42069
|
+
throw new ResourceContention(
|
|
42070
|
+
`Microsoft Graph reported conflict on lists.items.delete (${res.status})`,
|
|
42071
|
+
[]
|
|
42072
|
+
);
|
|
42073
|
+
}
|
|
42074
|
+
if (res.status === 404) {
|
|
42075
|
+
return {
|
|
42076
|
+
status: "committed",
|
|
42077
|
+
data: { id: itemId, deleted: true, alreadyMissing: true },
|
|
42078
|
+
committedAt: Date.now(),
|
|
42079
|
+
idempotentReplay: true
|
|
42080
|
+
};
|
|
42081
|
+
}
|
|
42082
|
+
if (!res.ok) {
|
|
42083
|
+
const text = await res.text().catch(() => "");
|
|
42084
|
+
throw new Error(`sharepoint lists.items.delete ${res.status}: ${text.slice(0, 200)}`);
|
|
42085
|
+
}
|
|
42086
|
+
return {
|
|
42087
|
+
status: "committed",
|
|
42088
|
+
data: { id: itemId, deleted: true },
|
|
42089
|
+
committedAt: Date.now(),
|
|
42090
|
+
idempotentReplay: false
|
|
42091
|
+
};
|
|
42092
|
+
}
|
|
42093
|
+
if (inv.capabilityName === "pages.publish") {
|
|
42094
|
+
const { siteId, pageId } = inv.args;
|
|
42095
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/pages/${encodeURIComponent(pageId)}/microsoft.graph.sitePage/publish`;
|
|
42096
|
+
const res = await fetch(url, {
|
|
42097
|
+
method: "POST",
|
|
42098
|
+
headers: {
|
|
42099
|
+
authorization: `Bearer ${accessToken}`,
|
|
42100
|
+
accept: "application/json"
|
|
42101
|
+
},
|
|
42102
|
+
signal: AbortSignal.timeout(15e3)
|
|
42103
|
+
});
|
|
42104
|
+
if (res.status === 401 || res.status === 403) {
|
|
42105
|
+
throw new CredentialsExpired(
|
|
42106
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42107
|
+
inv.source.id
|
|
42108
|
+
);
|
|
42109
|
+
}
|
|
42110
|
+
if (res.status === 409 || res.status === 412) {
|
|
42111
|
+
throw new ResourceContention(
|
|
42112
|
+
`Microsoft Graph reported conflict on pages.publish (${res.status})`,
|
|
42113
|
+
[]
|
|
42114
|
+
);
|
|
42115
|
+
}
|
|
42116
|
+
if (!res.ok) {
|
|
42117
|
+
const text = await res.text().catch(() => "");
|
|
42118
|
+
throw new Error(`sharepoint pages.publish ${res.status}: ${text.slice(0, 200)}`);
|
|
42119
|
+
}
|
|
42120
|
+
return {
|
|
42121
|
+
status: "committed",
|
|
42122
|
+
data: { id: pageId, published: true },
|
|
42123
|
+
committedAt: Date.now(),
|
|
42124
|
+
idempotentReplay: false
|
|
42125
|
+
};
|
|
42126
|
+
}
|
|
41817
42127
|
throw new Error(`sharepoint: unknown mutation capability ${inv.capabilityName}`);
|
|
41818
42128
|
},
|
|
41819
42129
|
async exchangeOAuth(input) {
|
|
@@ -41821,7 +42131,7 @@ function sharepoint(opts) {
|
|
|
41821
42131
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
41822
42132
|
}
|
|
41823
42133
|
const tokens = await exchangeAuthorizationCode({
|
|
41824
|
-
tokenUrl:
|
|
42134
|
+
tokenUrl: TOKEN_URL17,
|
|
41825
42135
|
clientId,
|
|
41826
42136
|
clientSecret,
|
|
41827
42137
|
code: input.code,
|
|
@@ -41844,7 +42154,7 @@ function sharepoint(opts) {
|
|
|
41844
42154
|
throw new Error("sharepoint.refreshToken: missing refresh token");
|
|
41845
42155
|
}
|
|
41846
42156
|
const refreshed = await refreshAccessToken({
|
|
41847
|
-
tokenUrl:
|
|
42157
|
+
tokenUrl: TOKEN_URL17,
|
|
41848
42158
|
clientId,
|
|
41849
42159
|
clientSecret,
|
|
41850
42160
|
refreshToken: creds.refreshToken
|
|
@@ -41893,7 +42203,7 @@ async function ensureFreshAccessToken15(creds, clientId, clientSecret) {
|
|
|
41893
42203
|
throw new CredentialsExpired("SharePoint access token expired and no refresh token", "");
|
|
41894
42204
|
}
|
|
41895
42205
|
const refreshed = await refreshAccessToken({
|
|
41896
|
-
tokenUrl:
|
|
42206
|
+
tokenUrl: TOKEN_URL17,
|
|
41897
42207
|
clientId,
|
|
41898
42208
|
clientSecret,
|
|
41899
42209
|
refreshToken: creds.refreshToken
|
|
@@ -71101,6 +71411,609 @@ var googleSearchConsoleConnector = declarativeRestConnector({
|
|
|
71101
71411
|
]
|
|
71102
71412
|
});
|
|
71103
71413
|
|
|
71414
|
+
// src/connectors/adapters/google-analytics.ts
|
|
71415
|
+
var googleAnalyticsConnector = declarativeRestConnector({
|
|
71416
|
+
kind: "google-analytics",
|
|
71417
|
+
displayName: "Google Analytics",
|
|
71418
|
+
description: "Run reports, pivot reports, realtime reports, and batch reports against connected GA4 properties. Read-only: GA4 ingest happens through gtag / Measurement Protocol, not the management API.",
|
|
71419
|
+
auth: {
|
|
71420
|
+
kind: "oauth2",
|
|
71421
|
+
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
71422
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
71423
|
+
scopes: ["https://www.googleapis.com/auth/analytics.readonly"],
|
|
71424
|
+
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
71425
|
+
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
71426
|
+
extraAuthParams: { access_type: "offline", prompt: "consent", include_granted_scopes: "true" }
|
|
71427
|
+
},
|
|
71428
|
+
category: "database",
|
|
71429
|
+
defaultConsistencyModel: "cache",
|
|
71430
|
+
baseUrl: "https://analyticsdata.googleapis.com",
|
|
71431
|
+
// accountSummaries.list lives on the Admin API host and is the cheapest
|
|
71432
|
+
// probe that confirms the token can reach GA4 at all. Absolute URL routes
|
|
71433
|
+
// around the single-baseUrl constraint of the declarative-rest runtime.
|
|
71434
|
+
test: {
|
|
71435
|
+
method: "GET",
|
|
71436
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
|
|
71437
|
+
query: { pageSize: 1 }
|
|
71438
|
+
},
|
|
71439
|
+
capabilities: [
|
|
71440
|
+
{
|
|
71441
|
+
name: "accountSummaries.list",
|
|
71442
|
+
class: "read",
|
|
71443
|
+
description: "List GA4 account summaries reachable by the connected identity. Each summary nests its properties so the agent can discover propertyId values without a second round-trip (GET analyticsadmin.googleapis.com/v1beta/accountSummaries).",
|
|
71444
|
+
parameters: {
|
|
71445
|
+
type: "object",
|
|
71446
|
+
properties: {
|
|
71447
|
+
pageSize: { type: "integer", minimum: 1, maximum: 200, description: "Max account summaries per page; server caps at 200." },
|
|
71448
|
+
pageToken: { type: "string", description: "Continuation token returned by a prior call." }
|
|
71449
|
+
}
|
|
71450
|
+
},
|
|
71451
|
+
request: {
|
|
71452
|
+
method: "GET",
|
|
71453
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
|
|
71454
|
+
query: { pageSize: "{pageSize}", pageToken: "{pageToken}" }
|
|
71455
|
+
},
|
|
71456
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71457
|
+
},
|
|
71458
|
+
{
|
|
71459
|
+
name: "properties.get",
|
|
71460
|
+
class: "read",
|
|
71461
|
+
description: "Fetch GA4 property settings (display name, timezone, currency, industry) by numeric property id (GET analyticsadmin.googleapis.com/v1beta/properties/{propertyId}).",
|
|
71462
|
+
parameters: {
|
|
71463
|
+
type: "object",
|
|
71464
|
+
properties: {
|
|
71465
|
+
propertyId: { type: "string", description: 'Numeric GA4 property id, e.g. "123456789".' }
|
|
71466
|
+
},
|
|
71467
|
+
required: ["propertyId"]
|
|
71468
|
+
},
|
|
71469
|
+
request: {
|
|
71470
|
+
method: "GET",
|
|
71471
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/properties/{propertyId}"
|
|
71472
|
+
},
|
|
71473
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71474
|
+
},
|
|
71475
|
+
{
|
|
71476
|
+
name: "properties.metadata.get",
|
|
71477
|
+
class: "read",
|
|
71478
|
+
description: "List every dimension and metric available on a GA4 property, including custom dimensions/metrics defined by the customer. Use this before runReport to discover valid dimension/metric names (GET /v1beta/properties/{propertyId}/metadata).",
|
|
71479
|
+
parameters: {
|
|
71480
|
+
type: "object",
|
|
71481
|
+
properties: {
|
|
71482
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." }
|
|
71483
|
+
},
|
|
71484
|
+
required: ["propertyId"]
|
|
71485
|
+
},
|
|
71486
|
+
request: {
|
|
71487
|
+
method: "GET",
|
|
71488
|
+
path: "/v1beta/properties/{propertyId}/metadata"
|
|
71489
|
+
},
|
|
71490
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71491
|
+
},
|
|
71492
|
+
{
|
|
71493
|
+
name: "properties.runReport",
|
|
71494
|
+
class: "read",
|
|
71495
|
+
description: 'Run a core report against a GA4 property. Pass dimensions, metrics, dateRanges (e.g. {startDate:"7daysAgo",endDate:"today"}), optional filters, ordering, and a row limit. Returns the rows, totals, and metadata GA4 emits in the standard runReport response (POST /v1beta/properties/{propertyId}:runReport).',
|
|
71496
|
+
parameters: {
|
|
71497
|
+
type: "object",
|
|
71498
|
+
properties: {
|
|
71499
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71500
|
+
dimensions: {
|
|
71501
|
+
type: "array",
|
|
71502
|
+
description: 'Dimension specs, e.g. [{ "name": "country" }, { "name": "deviceCategory" }].',
|
|
71503
|
+
items: {
|
|
71504
|
+
type: "object",
|
|
71505
|
+
properties: {
|
|
71506
|
+
name: { type: "string" },
|
|
71507
|
+
dimensionExpression: { type: "object", description: "Composite/lower-case/concatenate expression (optional)." }
|
|
71508
|
+
},
|
|
71509
|
+
required: ["name"]
|
|
71510
|
+
}
|
|
71511
|
+
},
|
|
71512
|
+
metrics: {
|
|
71513
|
+
type: "array",
|
|
71514
|
+
description: 'Metric specs, e.g. [{ "name": "activeUsers" }, { "name": "sessions" }].',
|
|
71515
|
+
items: {
|
|
71516
|
+
type: "object",
|
|
71517
|
+
properties: {
|
|
71518
|
+
name: { type: "string" },
|
|
71519
|
+
expression: { type: "string", description: "Derived metric expression (optional)." },
|
|
71520
|
+
invisible: { type: "boolean" }
|
|
71521
|
+
},
|
|
71522
|
+
required: ["name"]
|
|
71523
|
+
}
|
|
71524
|
+
},
|
|
71525
|
+
dateRanges: {
|
|
71526
|
+
type: "array",
|
|
71527
|
+
description: 'One or two date ranges; GA4 accepts ISO dates ("2026-05-01"), "today", "yesterday", or "NdaysAgo".',
|
|
71528
|
+
items: {
|
|
71529
|
+
type: "object",
|
|
71530
|
+
properties: {
|
|
71531
|
+
startDate: { type: "string" },
|
|
71532
|
+
endDate: { type: "string" },
|
|
71533
|
+
name: { type: "string", description: "Optional label included in the response row keys when comparing two ranges." }
|
|
71534
|
+
},
|
|
71535
|
+
required: ["startDate", "endDate"]
|
|
71536
|
+
}
|
|
71537
|
+
},
|
|
71538
|
+
dimensionFilter: { type: "object", description: "GA4 FilterExpression (and/or/not) applied to dimensions." },
|
|
71539
|
+
metricFilter: { type: "object", description: "GA4 FilterExpression applied to metrics after aggregation." },
|
|
71540
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71541
|
+
limit: { type: "integer", minimum: 1, maximum: 25e4, description: "Max rows per page; GA4 caps at 250000." },
|
|
71542
|
+
offset: { type: "integer", minimum: 0 },
|
|
71543
|
+
keepEmptyRows: { type: "boolean" },
|
|
71544
|
+
returnPropertyQuota: { type: "boolean", description: "Include per-property quota consumption in the response \u2014 useful for back-pressure decisions." },
|
|
71545
|
+
currencyCode: { type: "string", description: "ISO-4217 currency, overrides the property default for monetary metrics." },
|
|
71546
|
+
cohortSpec: { type: "object", description: "CohortSpec for cohort analysis (optional)." }
|
|
71547
|
+
},
|
|
71548
|
+
required: ["propertyId", "metrics", "dateRanges"]
|
|
71549
|
+
},
|
|
71550
|
+
request: {
|
|
71551
|
+
method: "POST",
|
|
71552
|
+
path: "/v1beta/properties/{propertyId}:runReport",
|
|
71553
|
+
body: {
|
|
71554
|
+
dimensions: "{dimensions}",
|
|
71555
|
+
metrics: "{metrics}",
|
|
71556
|
+
dateRanges: "{dateRanges}",
|
|
71557
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71558
|
+
metricFilter: "{metricFilter}",
|
|
71559
|
+
orderBys: "{orderBys}",
|
|
71560
|
+
limit: "{limit}",
|
|
71561
|
+
offset: "{offset}",
|
|
71562
|
+
keepEmptyRows: "{keepEmptyRows}",
|
|
71563
|
+
returnPropertyQuota: "{returnPropertyQuota}",
|
|
71564
|
+
currencyCode: "{currencyCode}",
|
|
71565
|
+
cohortSpec: "{cohortSpec}"
|
|
71566
|
+
}
|
|
71567
|
+
},
|
|
71568
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71569
|
+
},
|
|
71570
|
+
{
|
|
71571
|
+
name: "properties.batchRunReports",
|
|
71572
|
+
class: "read",
|
|
71573
|
+
description: "Run up to 5 reports against the same GA4 property in a single request \u2014 cheaper than 5 round-trips and counted as fewer quota tokens (POST /v1beta/properties/{propertyId}:batchRunReports).",
|
|
71574
|
+
parameters: {
|
|
71575
|
+
type: "object",
|
|
71576
|
+
properties: {
|
|
71577
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71578
|
+
requests: {
|
|
71579
|
+
type: "array",
|
|
71580
|
+
description: "Up to 5 report requests; each takes the same shape as runReport (dimensions/metrics/dateRanges/etc.).",
|
|
71581
|
+
items: { type: "object" },
|
|
71582
|
+
maxItems: 5
|
|
71583
|
+
}
|
|
71584
|
+
},
|
|
71585
|
+
required: ["propertyId", "requests"]
|
|
71586
|
+
},
|
|
71587
|
+
request: {
|
|
71588
|
+
method: "POST",
|
|
71589
|
+
path: "/v1beta/properties/{propertyId}:batchRunReports",
|
|
71590
|
+
body: { requests: "{requests}" }
|
|
71591
|
+
},
|
|
71592
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71593
|
+
},
|
|
71594
|
+
{
|
|
71595
|
+
name: "properties.runPivotReport",
|
|
71596
|
+
class: "read",
|
|
71597
|
+
description: "Run a pivot report \u2014 like runReport but with one or more pivot specifications that rotate dimensions into columns (POST /v1beta/properties/{propertyId}:runPivotReport).",
|
|
71598
|
+
parameters: {
|
|
71599
|
+
type: "object",
|
|
71600
|
+
properties: {
|
|
71601
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71602
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71603
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71604
|
+
dateRanges: { type: "array", items: { type: "object" } },
|
|
71605
|
+
pivots: {
|
|
71606
|
+
type: "array",
|
|
71607
|
+
description: "Pivot specifications \u2014 each names the dimensions to pivot, an order, a limit, and optional offset.",
|
|
71608
|
+
items: {
|
|
71609
|
+
type: "object",
|
|
71610
|
+
properties: {
|
|
71611
|
+
fieldNames: { type: "array", items: { type: "string" } },
|
|
71612
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71613
|
+
offset: { type: "string", description: "String-encoded long." },
|
|
71614
|
+
limit: { type: "string", description: "String-encoded long." },
|
|
71615
|
+
metricAggregations: { type: "array", items: { type: "string" } }
|
|
71616
|
+
},
|
|
71617
|
+
required: ["fieldNames"]
|
|
71618
|
+
}
|
|
71619
|
+
},
|
|
71620
|
+
dimensionFilter: { type: "object" },
|
|
71621
|
+
metricFilter: { type: "object" },
|
|
71622
|
+
currencyCode: { type: "string" },
|
|
71623
|
+
cohortSpec: { type: "object" },
|
|
71624
|
+
keepEmptyRows: { type: "boolean" },
|
|
71625
|
+
returnPropertyQuota: { type: "boolean" }
|
|
71626
|
+
},
|
|
71627
|
+
required: ["propertyId", "metrics", "dateRanges", "pivots"]
|
|
71628
|
+
},
|
|
71629
|
+
request: {
|
|
71630
|
+
method: "POST",
|
|
71631
|
+
path: "/v1beta/properties/{propertyId}:runPivotReport",
|
|
71632
|
+
body: {
|
|
71633
|
+
dimensions: "{dimensions}",
|
|
71634
|
+
metrics: "{metrics}",
|
|
71635
|
+
dateRanges: "{dateRanges}",
|
|
71636
|
+
pivots: "{pivots}",
|
|
71637
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71638
|
+
metricFilter: "{metricFilter}",
|
|
71639
|
+
currencyCode: "{currencyCode}",
|
|
71640
|
+
cohortSpec: "{cohortSpec}",
|
|
71641
|
+
keepEmptyRows: "{keepEmptyRows}",
|
|
71642
|
+
returnPropertyQuota: "{returnPropertyQuota}"
|
|
71643
|
+
}
|
|
71644
|
+
},
|
|
71645
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71646
|
+
},
|
|
71647
|
+
{
|
|
71648
|
+
name: "properties.runRealtimeReport",
|
|
71649
|
+
class: "read",
|
|
71650
|
+
description: "Run a realtime report \u2014 surfaces events that happened in the last 30 minutes. No dateRanges; the realtime window is implicit (POST /v1beta/properties/{propertyId}:runRealtimeReport).",
|
|
71651
|
+
parameters: {
|
|
71652
|
+
type: "object",
|
|
71653
|
+
properties: {
|
|
71654
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71655
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71656
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71657
|
+
dimensionFilter: { type: "object" },
|
|
71658
|
+
metricFilter: { type: "object" },
|
|
71659
|
+
limit: { type: "integer", minimum: 1, maximum: 25e4 },
|
|
71660
|
+
metricAggregations: { type: "array", items: { type: "string" } },
|
|
71661
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71662
|
+
returnPropertyQuota: { type: "boolean" },
|
|
71663
|
+
minuteRanges: {
|
|
71664
|
+
type: "array",
|
|
71665
|
+
description: 'Optional minute-window specifications, e.g. [{ "name": "last5", "startMinutesAgo": 5, "endMinutesAgo": 0 }]. Defaults to the last 30 minutes.',
|
|
71666
|
+
items: {
|
|
71667
|
+
type: "object",
|
|
71668
|
+
properties: {
|
|
71669
|
+
name: { type: "string" },
|
|
71670
|
+
startMinutesAgo: { type: "integer", minimum: 0, maximum: 29 },
|
|
71671
|
+
endMinutesAgo: { type: "integer", minimum: 0, maximum: 29 }
|
|
71672
|
+
}
|
|
71673
|
+
}
|
|
71674
|
+
}
|
|
71675
|
+
},
|
|
71676
|
+
required: ["propertyId", "metrics"]
|
|
71677
|
+
},
|
|
71678
|
+
request: {
|
|
71679
|
+
method: "POST",
|
|
71680
|
+
path: "/v1beta/properties/{propertyId}:runRealtimeReport",
|
|
71681
|
+
body: {
|
|
71682
|
+
dimensions: "{dimensions}",
|
|
71683
|
+
metrics: "{metrics}",
|
|
71684
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71685
|
+
metricFilter: "{metricFilter}",
|
|
71686
|
+
limit: "{limit}",
|
|
71687
|
+
metricAggregations: "{metricAggregations}",
|
|
71688
|
+
orderBys: "{orderBys}",
|
|
71689
|
+
returnPropertyQuota: "{returnPropertyQuota}",
|
|
71690
|
+
minuteRanges: "{minuteRanges}"
|
|
71691
|
+
}
|
|
71692
|
+
},
|
|
71693
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71694
|
+
},
|
|
71695
|
+
{
|
|
71696
|
+
name: "properties.checkCompatibility",
|
|
71697
|
+
class: "read",
|
|
71698
|
+
description: "Check whether a given dimension/metric combination is compatible before issuing a full runReport \u2014 GA4 rejects incompatible combos (e.g. cohort dimensions with non-cohort metrics) with a hard error (POST /v1beta/properties/{propertyId}:checkCompatibility).",
|
|
71699
|
+
parameters: {
|
|
71700
|
+
type: "object",
|
|
71701
|
+
properties: {
|
|
71702
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71703
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71704
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71705
|
+
dimensionFilter: { type: "object" },
|
|
71706
|
+
metricFilter: { type: "object" },
|
|
71707
|
+
compatibilityFilter: {
|
|
71708
|
+
type: "string",
|
|
71709
|
+
enum: ["COMPATIBILITY_UNSPECIFIED", "COMPATIBLE", "INCOMPATIBLE"],
|
|
71710
|
+
description: "Restrict the response to compatible or incompatible entries only."
|
|
71711
|
+
}
|
|
71712
|
+
},
|
|
71713
|
+
required: ["propertyId"]
|
|
71714
|
+
},
|
|
71715
|
+
request: {
|
|
71716
|
+
method: "POST",
|
|
71717
|
+
path: "/v1beta/properties/{propertyId}:checkCompatibility",
|
|
71718
|
+
body: {
|
|
71719
|
+
dimensions: "{dimensions}",
|
|
71720
|
+
metrics: "{metrics}",
|
|
71721
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71722
|
+
metricFilter: "{metricFilter}",
|
|
71723
|
+
compatibilityFilter: "{compatibilityFilter}"
|
|
71724
|
+
}
|
|
71725
|
+
},
|
|
71726
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71727
|
+
}
|
|
71728
|
+
]
|
|
71729
|
+
});
|
|
71730
|
+
|
|
71731
|
+
// src/connectors/adapters/google-meet.ts
|
|
71732
|
+
var googleMeetConnector = declarativeRestConnector({
|
|
71733
|
+
kind: "google-meet",
|
|
71734
|
+
displayName: "Google Meet",
|
|
71735
|
+
description: "Create Google Meet spaces, fetch post-meeting conference records, and read participants, recordings, and transcripts via the Google Meet REST API v2.",
|
|
71736
|
+
auth: {
|
|
71737
|
+
kind: "oauth2",
|
|
71738
|
+
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
71739
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
71740
|
+
scopes: [
|
|
71741
|
+
"https://www.googleapis.com/auth/meetings.space.created",
|
|
71742
|
+
"https://www.googleapis.com/auth/meetings.space.readonly",
|
|
71743
|
+
"https://www.googleapis.com/auth/meetings.space.settings",
|
|
71744
|
+
"https://www.googleapis.com/auth/drive.readonly"
|
|
71745
|
+
],
|
|
71746
|
+
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
71747
|
+
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
71748
|
+
extraAuthParams: {
|
|
71749
|
+
access_type: "offline",
|
|
71750
|
+
prompt: "consent",
|
|
71751
|
+
include_granted_scopes: "true"
|
|
71752
|
+
}
|
|
71753
|
+
},
|
|
71754
|
+
category: "calendar",
|
|
71755
|
+
defaultConsistencyModel: "authoritative",
|
|
71756
|
+
baseUrl: "https://meet.googleapis.com",
|
|
71757
|
+
// /v2/spaces/{name} requires a real space id; the cheapest token-validity
|
|
71758
|
+
// probe Meet exposes is creating a throwaway space, which has a side effect
|
|
71759
|
+
// we don't want in a connection test. Skip the in-band test — the adapter
|
|
71760
|
+
// contract treats a missing `test` as ok and connection issuance still
|
|
71761
|
+
// catches the auth handshake at exchange time.
|
|
71762
|
+
capabilities: [
|
|
71763
|
+
{
|
|
71764
|
+
name: "spaces.create",
|
|
71765
|
+
class: "mutation",
|
|
71766
|
+
description: "Create a Meet space and return its meet.google.com URL. The space lives until the calling user deletes it or it expires per Google retention rules.",
|
|
71767
|
+
parameters: {
|
|
71768
|
+
type: "object",
|
|
71769
|
+
properties: {
|
|
71770
|
+
config: {
|
|
71771
|
+
type: "object",
|
|
71772
|
+
description: "Optional SpaceConfig: accessType (OPEN | TRUSTED | RESTRICTED), entryPointAccess (ALL | CREATOR_APP_ONLY), moderation, attendanceReport, artifactConfig, chatRestriction, presentRestriction, defaultJoinAsViewerType."
|
|
71773
|
+
}
|
|
71774
|
+
}
|
|
71775
|
+
},
|
|
71776
|
+
request: {
|
|
71777
|
+
method: "POST",
|
|
71778
|
+
path: "/v2/spaces",
|
|
71779
|
+
body: {
|
|
71780
|
+
config: "{config}"
|
|
71781
|
+
}
|
|
71782
|
+
},
|
|
71783
|
+
// Meet's spaces.create is a pure side-effect; no upstream idempotency
|
|
71784
|
+
// key on this endpoint, so a retry produces a second space. Mark
|
|
71785
|
+
// accordingly so the MutationGuard layer enforces idempotency.
|
|
71786
|
+
cas: "none",
|
|
71787
|
+
externalEffect: true,
|
|
71788
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
|
|
71789
|
+
},
|
|
71790
|
+
{
|
|
71791
|
+
name: "spaces.get",
|
|
71792
|
+
class: "read",
|
|
71793
|
+
description: 'Read a Meet space by resource name (e.g. "spaces/abc-defg-hij") or by short meeting code.',
|
|
71794
|
+
parameters: {
|
|
71795
|
+
type: "object",
|
|
71796
|
+
properties: {
|
|
71797
|
+
name: {
|
|
71798
|
+
type: "string",
|
|
71799
|
+
description: 'Resource name like "spaces/{space_id}" or "spaces/{meeting_code}".'
|
|
71800
|
+
}
|
|
71801
|
+
},
|
|
71802
|
+
required: ["name"]
|
|
71803
|
+
},
|
|
71804
|
+
request: {
|
|
71805
|
+
method: "GET",
|
|
71806
|
+
path: "/v2/{name}"
|
|
71807
|
+
},
|
|
71808
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71809
|
+
},
|
|
71810
|
+
{
|
|
71811
|
+
name: "spaces.update",
|
|
71812
|
+
class: "mutation",
|
|
71813
|
+
description: "Patch a Meet space (accessType, entryPointAccess, moderation toggles, artifactConfig, chat/present restrictions). Caller supplies updateMask to specify mutated fields.",
|
|
71814
|
+
parameters: {
|
|
71815
|
+
type: "object",
|
|
71816
|
+
properties: {
|
|
71817
|
+
name: { type: "string", description: 'Resource name like "spaces/{space_id}".' },
|
|
71818
|
+
updateMask: {
|
|
71819
|
+
type: "string",
|
|
71820
|
+
description: 'Comma-separated FieldMask of mutated fields, e.g. "config.accessType,config.moderation".'
|
|
71821
|
+
},
|
|
71822
|
+
config: { type: "object", description: "New SpaceConfig values." }
|
|
71823
|
+
},
|
|
71824
|
+
required: ["name"]
|
|
71825
|
+
},
|
|
71826
|
+
request: {
|
|
71827
|
+
method: "PATCH",
|
|
71828
|
+
path: "/v2/{name}",
|
|
71829
|
+
query: {
|
|
71830
|
+
updateMask: "{updateMask}"
|
|
71831
|
+
},
|
|
71832
|
+
body: {
|
|
71833
|
+
config: "{config}"
|
|
71834
|
+
}
|
|
71835
|
+
},
|
|
71836
|
+
cas: "native-idempotency",
|
|
71837
|
+
externalEffect: true,
|
|
71838
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.settings"]
|
|
71839
|
+
},
|
|
71840
|
+
{
|
|
71841
|
+
name: "spaces.endActiveConference",
|
|
71842
|
+
class: "mutation",
|
|
71843
|
+
description: "Terminate the currently active conference inside a Meet space. No-op (HTTP 200) if no conference is active.",
|
|
71844
|
+
parameters: {
|
|
71845
|
+
type: "object",
|
|
71846
|
+
properties: {
|
|
71847
|
+
name: { type: "string", description: 'Resource name like "spaces/{space_id}".' }
|
|
71848
|
+
},
|
|
71849
|
+
required: ["name"]
|
|
71850
|
+
},
|
|
71851
|
+
request: {
|
|
71852
|
+
method: "POST",
|
|
71853
|
+
path: "/v2/{name}:endActiveConference",
|
|
71854
|
+
body: {}
|
|
71855
|
+
},
|
|
71856
|
+
cas: "native-idempotency",
|
|
71857
|
+
externalEffect: true,
|
|
71858
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
|
|
71859
|
+
},
|
|
71860
|
+
{
|
|
71861
|
+
name: "conferenceRecords.list",
|
|
71862
|
+
class: "read",
|
|
71863
|
+
description: "List conference records for meetings the calling user attended or hosted. Supports server-side filtering by space.name and end_time.",
|
|
71864
|
+
parameters: {
|
|
71865
|
+
type: "object",
|
|
71866
|
+
properties: {
|
|
71867
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71868
|
+
pageToken: { type: "string" },
|
|
71869
|
+
filter: {
|
|
71870
|
+
type: "string",
|
|
71871
|
+
description: `EBNF filter, e.g. 'space.name="spaces/abc"' or 'end_time>="2024-01-01T00:00:00Z"'.`
|
|
71872
|
+
}
|
|
71873
|
+
}
|
|
71874
|
+
},
|
|
71875
|
+
request: {
|
|
71876
|
+
method: "GET",
|
|
71877
|
+
path: "/v2/conferenceRecords",
|
|
71878
|
+
query: {
|
|
71879
|
+
pageSize: "{pageSize}",
|
|
71880
|
+
pageToken: "{pageToken}",
|
|
71881
|
+
filter: "{filter}"
|
|
71882
|
+
}
|
|
71883
|
+
},
|
|
71884
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71885
|
+
},
|
|
71886
|
+
{
|
|
71887
|
+
name: "conferenceRecords.get",
|
|
71888
|
+
class: "read",
|
|
71889
|
+
description: 'Read a conference record by resource name (e.g. "conferenceRecords/abc123").',
|
|
71890
|
+
parameters: {
|
|
71891
|
+
type: "object",
|
|
71892
|
+
properties: {
|
|
71893
|
+
name: { type: "string", description: 'Resource name like "conferenceRecords/{conference_record_id}".' }
|
|
71894
|
+
},
|
|
71895
|
+
required: ["name"]
|
|
71896
|
+
},
|
|
71897
|
+
request: {
|
|
71898
|
+
method: "GET",
|
|
71899
|
+
path: "/v2/{name}"
|
|
71900
|
+
},
|
|
71901
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71902
|
+
},
|
|
71903
|
+
{
|
|
71904
|
+
name: "conferenceRecords.participants.list",
|
|
71905
|
+
class: "read",
|
|
71906
|
+
description: "List participants for a finished conference, including anonymous and phone-dial-in attendees.",
|
|
71907
|
+
parameters: {
|
|
71908
|
+
type: "object",
|
|
71909
|
+
properties: {
|
|
71910
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71911
|
+
pageSize: { type: "integer", minimum: 1, maximum: 250 },
|
|
71912
|
+
pageToken: { type: "string" },
|
|
71913
|
+
filter: { type: "string", description: `EBNF filter, e.g. 'earliest_start_time<="2024-01-01T00:00:00Z"'.` }
|
|
71914
|
+
},
|
|
71915
|
+
required: ["parent"]
|
|
71916
|
+
},
|
|
71917
|
+
request: {
|
|
71918
|
+
method: "GET",
|
|
71919
|
+
path: "/v2/{parent}/participants",
|
|
71920
|
+
query: {
|
|
71921
|
+
pageSize: "{pageSize}",
|
|
71922
|
+
pageToken: "{pageToken}",
|
|
71923
|
+
filter: "{filter}"
|
|
71924
|
+
}
|
|
71925
|
+
},
|
|
71926
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71927
|
+
},
|
|
71928
|
+
{
|
|
71929
|
+
name: "conferenceRecords.recordings.list",
|
|
71930
|
+
class: "read",
|
|
71931
|
+
description: "List recordings for a conference record. Each entry includes the Drive file id and DriveFileExportUri for downstream Drive fetches.",
|
|
71932
|
+
parameters: {
|
|
71933
|
+
type: "object",
|
|
71934
|
+
properties: {
|
|
71935
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71936
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71937
|
+
pageToken: { type: "string" }
|
|
71938
|
+
},
|
|
71939
|
+
required: ["parent"]
|
|
71940
|
+
},
|
|
71941
|
+
request: {
|
|
71942
|
+
method: "GET",
|
|
71943
|
+
path: "/v2/{parent}/recordings",
|
|
71944
|
+
query: {
|
|
71945
|
+
pageSize: "{pageSize}",
|
|
71946
|
+
pageToken: "{pageToken}"
|
|
71947
|
+
}
|
|
71948
|
+
},
|
|
71949
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71950
|
+
},
|
|
71951
|
+
{
|
|
71952
|
+
name: "conferenceRecords.recordings.get",
|
|
71953
|
+
class: "read",
|
|
71954
|
+
description: "Read a single recording by resource name.",
|
|
71955
|
+
parameters: {
|
|
71956
|
+
type: "object",
|
|
71957
|
+
properties: {
|
|
71958
|
+
name: {
|
|
71959
|
+
type: "string",
|
|
71960
|
+
description: 'Resource name like "conferenceRecords/{conference_record_id}/recordings/{recording_id}".'
|
|
71961
|
+
}
|
|
71962
|
+
},
|
|
71963
|
+
required: ["name"]
|
|
71964
|
+
},
|
|
71965
|
+
request: {
|
|
71966
|
+
method: "GET",
|
|
71967
|
+
path: "/v2/{name}"
|
|
71968
|
+
},
|
|
71969
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71970
|
+
},
|
|
71971
|
+
{
|
|
71972
|
+
name: "conferenceRecords.transcripts.list",
|
|
71973
|
+
class: "read",
|
|
71974
|
+
description: "List transcripts (auto-generated captions exports) for a conference record.",
|
|
71975
|
+
parameters: {
|
|
71976
|
+
type: "object",
|
|
71977
|
+
properties: {
|
|
71978
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71979
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71980
|
+
pageToken: { type: "string" }
|
|
71981
|
+
},
|
|
71982
|
+
required: ["parent"]
|
|
71983
|
+
},
|
|
71984
|
+
request: {
|
|
71985
|
+
method: "GET",
|
|
71986
|
+
path: "/v2/{parent}/transcripts",
|
|
71987
|
+
query: {
|
|
71988
|
+
pageSize: "{pageSize}",
|
|
71989
|
+
pageToken: "{pageToken}"
|
|
71990
|
+
}
|
|
71991
|
+
},
|
|
71992
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71993
|
+
},
|
|
71994
|
+
{
|
|
71995
|
+
name: "conferenceRecords.transcripts.get",
|
|
71996
|
+
class: "read",
|
|
71997
|
+
description: "Read a transcript by resource name; payload links to the Drive Doc holding the transcript text.",
|
|
71998
|
+
parameters: {
|
|
71999
|
+
type: "object",
|
|
72000
|
+
properties: {
|
|
72001
|
+
name: {
|
|
72002
|
+
type: "string",
|
|
72003
|
+
description: 'Resource name like "conferenceRecords/{conference_record_id}/transcripts/{transcript_id}".'
|
|
72004
|
+
}
|
|
72005
|
+
},
|
|
72006
|
+
required: ["name"]
|
|
72007
|
+
},
|
|
72008
|
+
request: {
|
|
72009
|
+
method: "GET",
|
|
72010
|
+
path: "/v2/{name}"
|
|
72011
|
+
},
|
|
72012
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
72013
|
+
}
|
|
72014
|
+
]
|
|
72015
|
+
});
|
|
72016
|
+
|
|
71104
72017
|
// src/connectors/adapters/youtube-data.ts
|
|
71105
72018
|
var youtubeDataConnector = declarativeRestConnector({
|
|
71106
72019
|
kind: "youtube",
|
|
@@ -86864,123 +87777,6 @@ var microsoftPowerBiConnector = declarativeRestConnector({
|
|
|
86864
87777
|
]
|
|
86865
87778
|
});
|
|
86866
87779
|
|
|
86867
|
-
// src/connectors/adapters/microsoft-outlook-calendar.ts
|
|
86868
|
-
var microsoftOutlookCalendarConnector = declarativeRestConnector({
|
|
86869
|
-
kind: "microsoft-outlook-calendar",
|
|
86870
|
-
displayName: "Microsoft Outlook Calendar",
|
|
86871
|
-
description: "Create, list, and delete Outlook/Microsoft 365 calendar events via Microsoft Graph.",
|
|
86872
|
-
auth: {
|
|
86873
|
-
kind: "oauth2",
|
|
86874
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
86875
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
86876
|
-
scopes: ["offline_access", "Calendars.ReadWrite", "User.Read"],
|
|
86877
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
86878
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
86879
|
-
},
|
|
86880
|
-
category: "calendar",
|
|
86881
|
-
defaultConsistencyModel: "authoritative",
|
|
86882
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
86883
|
-
test: { method: "GET", path: "/me" },
|
|
86884
|
-
capabilities: [
|
|
86885
|
-
{
|
|
86886
|
-
name: "create.event",
|
|
86887
|
-
class: "mutation",
|
|
86888
|
-
description: "Create a calendar event on the signed-in user's primary calendar, or on a specific calendarId when supplied.",
|
|
86889
|
-
parameters: {
|
|
86890
|
-
type: "object",
|
|
86891
|
-
properties: {
|
|
86892
|
-
calendarId: { type: "string" },
|
|
86893
|
-
subject: { type: "string" },
|
|
86894
|
-
body: { type: "object" },
|
|
86895
|
-
start: { type: "object" },
|
|
86896
|
-
end: { type: "object" },
|
|
86897
|
-
location: { type: "object" },
|
|
86898
|
-
attendees: { type: "array", items: { type: "object" } },
|
|
86899
|
-
isOnlineMeeting: { type: "boolean" },
|
|
86900
|
-
onlineMeetingProvider: { type: "string" },
|
|
86901
|
-
showAs: { type: "string" },
|
|
86902
|
-
sensitivity: { type: "string" },
|
|
86903
|
-
importance: { type: "string" },
|
|
86904
|
-
categories: { type: "array", items: { type: "string" } },
|
|
86905
|
-
reminderMinutesBeforeStart: { type: "integer" },
|
|
86906
|
-
isAllDay: { type: "boolean" },
|
|
86907
|
-
recurrence: { type: "object" },
|
|
86908
|
-
transactionId: { type: "string" }
|
|
86909
|
-
},
|
|
86910
|
-
required: ["subject", "start", "end"]
|
|
86911
|
-
},
|
|
86912
|
-
request: {
|
|
86913
|
-
method: "POST",
|
|
86914
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86915
|
-
body: {
|
|
86916
|
-
subject: "{subject}",
|
|
86917
|
-
body: "{body}",
|
|
86918
|
-
start: "{start}",
|
|
86919
|
-
end: "{end}",
|
|
86920
|
-
location: "{location}",
|
|
86921
|
-
attendees: "{attendees}",
|
|
86922
|
-
isOnlineMeeting: "{isOnlineMeeting}",
|
|
86923
|
-
onlineMeetingProvider: "{onlineMeetingProvider}",
|
|
86924
|
-
showAs: "{showAs}",
|
|
86925
|
-
sensitivity: "{sensitivity}",
|
|
86926
|
-
importance: "{importance}",
|
|
86927
|
-
categories: "{categories}",
|
|
86928
|
-
reminderMinutesBeforeStart: "{reminderMinutesBeforeStart}",
|
|
86929
|
-
isAllDay: "{isAllDay}",
|
|
86930
|
-
recurrence: "{recurrence}",
|
|
86931
|
-
transactionId: "{transactionId}"
|
|
86932
|
-
}
|
|
86933
|
-
},
|
|
86934
|
-
cas: "native-idempotency",
|
|
86935
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86936
|
-
},
|
|
86937
|
-
{
|
|
86938
|
-
name: "delete.event",
|
|
86939
|
-
class: "mutation",
|
|
86940
|
-
description: "Delete a calendar event by id from the signed-in user mailbox.",
|
|
86941
|
-
parameters: {
|
|
86942
|
-
type: "object",
|
|
86943
|
-
properties: { eventId: { type: "string" } },
|
|
86944
|
-
required: ["eventId"]
|
|
86945
|
-
},
|
|
86946
|
-
request: { method: "DELETE", path: "/me/events/{eventId}" },
|
|
86947
|
-
cas: "native-idempotency",
|
|
86948
|
-
externalEffect: true,
|
|
86949
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86950
|
-
},
|
|
86951
|
-
{
|
|
86952
|
-
name: "list.events",
|
|
86953
|
-
class: "read",
|
|
86954
|
-
description: "List events on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar unless calendarId is supplied.",
|
|
86955
|
-
parameters: {
|
|
86956
|
-
type: "object",
|
|
86957
|
-
properties: {
|
|
86958
|
-
calendarId: { type: "string" },
|
|
86959
|
-
$top: { type: "integer" },
|
|
86960
|
-
$skip: { type: "integer" },
|
|
86961
|
-
$filter: { type: "string" },
|
|
86962
|
-
$select: { type: "string" },
|
|
86963
|
-
$orderby: { type: "string" },
|
|
86964
|
-
$search: { type: "string" }
|
|
86965
|
-
}
|
|
86966
|
-
},
|
|
86967
|
-
request: {
|
|
86968
|
-
method: "GET",
|
|
86969
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86970
|
-
query: {
|
|
86971
|
-
$top: "{$top}",
|
|
86972
|
-
$skip: "{$skip}",
|
|
86973
|
-
$filter: "{$filter}",
|
|
86974
|
-
$select: "{$select}",
|
|
86975
|
-
$orderby: "{$orderby}",
|
|
86976
|
-
$search: "{$search}"
|
|
86977
|
-
}
|
|
86978
|
-
},
|
|
86979
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86980
|
-
}
|
|
86981
|
-
]
|
|
86982
|
-
});
|
|
86983
|
-
|
|
86984
87780
|
// src/connectors/adapters/microsoft-onenote.ts
|
|
86985
87781
|
var microsoftOnenoteConnector = declarativeRestConnector({
|
|
86986
87782
|
kind: "microsoft-onenote",
|
|
@@ -87200,299 +87996,6 @@ var microsoftOnenoteConnector = declarativeRestConnector({
|
|
|
87200
87996
|
]
|
|
87201
87997
|
});
|
|
87202
87998
|
|
|
87203
|
-
// src/connectors/adapters/microsoft-outlook.ts
|
|
87204
|
-
var microsoftOutlookConnector = declarativeRestConnector({
|
|
87205
|
-
kind: "microsoft-outlook",
|
|
87206
|
-
displayName: "Microsoft Outlook",
|
|
87207
|
-
description: "Send, draft, reply to, forward, search, label, and organize email in the signed-in user's Outlook mailbox via Microsoft Graph.",
|
|
87208
|
-
auth: {
|
|
87209
|
-
kind: "oauth2",
|
|
87210
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
87211
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
87212
|
-
scopes: [
|
|
87213
|
-
"offline_access",
|
|
87214
|
-
"User.Read",
|
|
87215
|
-
"Mail.ReadWrite",
|
|
87216
|
-
"Mail.Send",
|
|
87217
|
-
"MailboxSettings.Read"
|
|
87218
|
-
],
|
|
87219
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
87220
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
87221
|
-
},
|
|
87222
|
-
category: "comms",
|
|
87223
|
-
defaultConsistencyModel: "authoritative",
|
|
87224
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
87225
|
-
test: { method: "GET", path: "/me" },
|
|
87226
|
-
capabilities: [
|
|
87227
|
-
{
|
|
87228
|
-
name: "email.send",
|
|
87229
|
-
class: "mutation",
|
|
87230
|
-
description: "Send an email immediately from the signed-in user's mailbox. Optionally saves the sent message to the Sent Items folder.",
|
|
87231
|
-
parameters: {
|
|
87232
|
-
type: "object",
|
|
87233
|
-
properties: {
|
|
87234
|
-
subject: { type: "string" },
|
|
87235
|
-
body: { type: "object" },
|
|
87236
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87237
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87238
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87239
|
-
attachments: { type: "array", items: { type: "object" } },
|
|
87240
|
-
saveToSentItems: { type: "boolean" }
|
|
87241
|
-
},
|
|
87242
|
-
required: ["subject", "body", "toRecipients"]
|
|
87243
|
-
},
|
|
87244
|
-
request: {
|
|
87245
|
-
method: "POST",
|
|
87246
|
-
path: "/me/sendMail",
|
|
87247
|
-
body: {
|
|
87248
|
-
message: {
|
|
87249
|
-
subject: "{subject}",
|
|
87250
|
-
body: "{body}",
|
|
87251
|
-
toRecipients: "{toRecipients}",
|
|
87252
|
-
ccRecipients: "{ccRecipients}",
|
|
87253
|
-
bccRecipients: "{bccRecipients}",
|
|
87254
|
-
attachments: "{attachments}"
|
|
87255
|
-
},
|
|
87256
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87257
|
-
}
|
|
87258
|
-
},
|
|
87259
|
-
cas: "none",
|
|
87260
|
-
externalEffect: true,
|
|
87261
|
-
requiredScopes: ["Mail.Send"]
|
|
87262
|
-
},
|
|
87263
|
-
{
|
|
87264
|
-
name: "email.draft.create",
|
|
87265
|
-
class: "mutation",
|
|
87266
|
-
description: "Create a draft email in the signed-in user mailbox without sending it.",
|
|
87267
|
-
parameters: {
|
|
87268
|
-
type: "object",
|
|
87269
|
-
properties: {
|
|
87270
|
-
subject: { type: "string" },
|
|
87271
|
-
body: { type: "object" },
|
|
87272
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87273
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87274
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87275
|
-
importance: { type: "string" },
|
|
87276
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87277
|
-
},
|
|
87278
|
-
required: ["subject", "body"]
|
|
87279
|
-
},
|
|
87280
|
-
request: {
|
|
87281
|
-
method: "POST",
|
|
87282
|
-
path: "/me/messages",
|
|
87283
|
-
body: {
|
|
87284
|
-
subject: "{subject}",
|
|
87285
|
-
body: "{body}",
|
|
87286
|
-
toRecipients: "{toRecipients}",
|
|
87287
|
-
ccRecipients: "{ccRecipients}",
|
|
87288
|
-
bccRecipients: "{bccRecipients}",
|
|
87289
|
-
importance: "{importance}",
|
|
87290
|
-
categories: "{categories}"
|
|
87291
|
-
}
|
|
87292
|
-
},
|
|
87293
|
-
cas: "native-idempotency",
|
|
87294
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87295
|
-
},
|
|
87296
|
-
{
|
|
87297
|
-
name: "email.draft.send",
|
|
87298
|
-
class: "mutation",
|
|
87299
|
-
description: "Send a previously created draft message by id.",
|
|
87300
|
-
parameters: {
|
|
87301
|
-
type: "object",
|
|
87302
|
-
properties: { messageId: { type: "string" } },
|
|
87303
|
-
required: ["messageId"]
|
|
87304
|
-
},
|
|
87305
|
-
request: { method: "POST", path: "/me/messages/{messageId}/send" },
|
|
87306
|
-
cas: "none",
|
|
87307
|
-
externalEffect: true,
|
|
87308
|
-
requiredScopes: ["Mail.Send"]
|
|
87309
|
-
},
|
|
87310
|
-
{
|
|
87311
|
-
name: "email.reply",
|
|
87312
|
-
class: "mutation",
|
|
87313
|
-
description: "Reply to an existing message. When comment is provided alone, Graph generates the reply body; when message is provided, it overrides recipients/body.",
|
|
87314
|
-
parameters: {
|
|
87315
|
-
type: "object",
|
|
87316
|
-
properties: {
|
|
87317
|
-
messageId: { type: "string" },
|
|
87318
|
-
comment: { type: "string" },
|
|
87319
|
-
message: { type: "object" }
|
|
87320
|
-
},
|
|
87321
|
-
required: ["messageId"]
|
|
87322
|
-
},
|
|
87323
|
-
request: {
|
|
87324
|
-
method: "POST",
|
|
87325
|
-
path: "/me/messages/{messageId}/reply",
|
|
87326
|
-
body: { comment: "{comment}", message: "{message}" }
|
|
87327
|
-
},
|
|
87328
|
-
cas: "none",
|
|
87329
|
-
externalEffect: true,
|
|
87330
|
-
requiredScopes: ["Mail.Send"]
|
|
87331
|
-
},
|
|
87332
|
-
{
|
|
87333
|
-
name: "email.forward",
|
|
87334
|
-
class: "mutation",
|
|
87335
|
-
description: "Forward an existing message to one or more recipients with an optional comment.",
|
|
87336
|
-
parameters: {
|
|
87337
|
-
type: "object",
|
|
87338
|
-
properties: {
|
|
87339
|
-
messageId: { type: "string" },
|
|
87340
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87341
|
-
comment: { type: "string" }
|
|
87342
|
-
},
|
|
87343
|
-
required: ["messageId", "toRecipients"]
|
|
87344
|
-
},
|
|
87345
|
-
request: {
|
|
87346
|
-
method: "POST",
|
|
87347
|
-
path: "/me/messages/{messageId}/forward",
|
|
87348
|
-
body: { toRecipients: "{toRecipients}", comment: "{comment}" }
|
|
87349
|
-
},
|
|
87350
|
-
cas: "none",
|
|
87351
|
-
externalEffect: true,
|
|
87352
|
-
requiredScopes: ["Mail.Send"]
|
|
87353
|
-
},
|
|
87354
|
-
{
|
|
87355
|
-
name: "email.move",
|
|
87356
|
-
class: "mutation",
|
|
87357
|
-
description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive).",
|
|
87358
|
-
parameters: {
|
|
87359
|
-
type: "object",
|
|
87360
|
-
properties: {
|
|
87361
|
-
messageId: { type: "string" },
|
|
87362
|
-
destinationId: { type: "string" }
|
|
87363
|
-
},
|
|
87364
|
-
required: ["messageId", "destinationId"]
|
|
87365
|
-
},
|
|
87366
|
-
request: {
|
|
87367
|
-
method: "POST",
|
|
87368
|
-
path: "/me/messages/{messageId}/move",
|
|
87369
|
-
body: { destinationId: "{destinationId}" }
|
|
87370
|
-
},
|
|
87371
|
-
cas: "native-idempotency",
|
|
87372
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87373
|
-
},
|
|
87374
|
-
{
|
|
87375
|
-
name: "email.label.add",
|
|
87376
|
-
class: "mutation",
|
|
87377
|
-
description: "Tag a message with one or more Outlook categories (labels). Pass the desired full set; Graph replaces the categories array.",
|
|
87378
|
-
parameters: {
|
|
87379
|
-
type: "object",
|
|
87380
|
-
properties: {
|
|
87381
|
-
messageId: { type: "string" },
|
|
87382
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87383
|
-
},
|
|
87384
|
-
required: ["messageId", "categories"]
|
|
87385
|
-
},
|
|
87386
|
-
request: {
|
|
87387
|
-
method: "PATCH",
|
|
87388
|
-
path: "/me/messages/{messageId}",
|
|
87389
|
-
body: { categories: "{categories}" }
|
|
87390
|
-
},
|
|
87391
|
-
cas: "optimistic-read-verify",
|
|
87392
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87393
|
-
},
|
|
87394
|
-
{
|
|
87395
|
-
name: "email.label.remove",
|
|
87396
|
-
class: "mutation",
|
|
87397
|
-
description: "Remove labels from a message by writing the surviving categories array. Caller computes the remaining set and supplies it explicitly.",
|
|
87398
|
-
parameters: {
|
|
87399
|
-
type: "object",
|
|
87400
|
-
properties: {
|
|
87401
|
-
messageId: { type: "string" },
|
|
87402
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87403
|
-
},
|
|
87404
|
-
required: ["messageId", "categories"]
|
|
87405
|
-
},
|
|
87406
|
-
request: {
|
|
87407
|
-
method: "PATCH",
|
|
87408
|
-
path: "/me/messages/{messageId}",
|
|
87409
|
-
body: { categories: "{categories}" }
|
|
87410
|
-
},
|
|
87411
|
-
cas: "optimistic-read-verify",
|
|
87412
|
-
externalEffect: true,
|
|
87413
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87414
|
-
},
|
|
87415
|
-
{
|
|
87416
|
-
name: "email.find",
|
|
87417
|
-
class: "read",
|
|
87418
|
-
description: "Search messages in a folder using OData $search/$filter with $top, $select, $orderby. Folder defaults to the well-known inbox if omitted.",
|
|
87419
|
-
parameters: {
|
|
87420
|
-
type: "object",
|
|
87421
|
-
properties: {
|
|
87422
|
-
mailFolderId: { type: "string" },
|
|
87423
|
-
$search: { type: "string" },
|
|
87424
|
-
$filter: { type: "string" },
|
|
87425
|
-
$select: { type: "string" },
|
|
87426
|
-
$top: { type: "integer" },
|
|
87427
|
-
$orderby: { type: "string" }
|
|
87428
|
-
}
|
|
87429
|
-
},
|
|
87430
|
-
request: {
|
|
87431
|
-
method: "GET",
|
|
87432
|
-
path: "/me/mailFolders/{mailFolderId}/messages",
|
|
87433
|
-
query: {
|
|
87434
|
-
$search: "{$search}",
|
|
87435
|
-
$filter: "{$filter}",
|
|
87436
|
-
$select: "{$select}",
|
|
87437
|
-
$top: "{$top}",
|
|
87438
|
-
$orderby: "{$orderby}"
|
|
87439
|
-
}
|
|
87440
|
-
},
|
|
87441
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87442
|
-
},
|
|
87443
|
-
{
|
|
87444
|
-
name: "email.attachment.download",
|
|
87445
|
-
class: "read",
|
|
87446
|
-
description: "Read an attachment record (metadata plus base64 contentBytes for file attachments) for a message by attachment id.",
|
|
87447
|
-
parameters: {
|
|
87448
|
-
type: "object",
|
|
87449
|
-
properties: {
|
|
87450
|
-
messageId: { type: "string" },
|
|
87451
|
-
attachmentId: { type: "string" }
|
|
87452
|
-
},
|
|
87453
|
-
required: ["messageId", "attachmentId"]
|
|
87454
|
-
},
|
|
87455
|
-
request: {
|
|
87456
|
-
method: "GET",
|
|
87457
|
-
path: "/me/messages/{messageId}/attachments/{attachmentId}"
|
|
87458
|
-
},
|
|
87459
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87460
|
-
},
|
|
87461
|
-
{
|
|
87462
|
-
name: "email.approval.request",
|
|
87463
|
-
class: "mutation",
|
|
87464
|
-
description: "Send an approval-request email by composing a structured message body and sending it through /me/sendMail. The body should encode the approval prompt and reply-handling instructions.",
|
|
87465
|
-
parameters: {
|
|
87466
|
-
type: "object",
|
|
87467
|
-
properties: {
|
|
87468
|
-
subject: { type: "string" },
|
|
87469
|
-
body: { type: "object" },
|
|
87470
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87471
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87472
|
-
saveToSentItems: { type: "boolean" }
|
|
87473
|
-
},
|
|
87474
|
-
required: ["subject", "body", "toRecipients"]
|
|
87475
|
-
},
|
|
87476
|
-
request: {
|
|
87477
|
-
method: "POST",
|
|
87478
|
-
path: "/me/sendMail",
|
|
87479
|
-
body: {
|
|
87480
|
-
message: {
|
|
87481
|
-
subject: "{subject}",
|
|
87482
|
-
body: "{body}",
|
|
87483
|
-
toRecipients: "{toRecipients}",
|
|
87484
|
-
ccRecipients: "{ccRecipients}"
|
|
87485
|
-
},
|
|
87486
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87487
|
-
}
|
|
87488
|
-
},
|
|
87489
|
-
cas: "none",
|
|
87490
|
-
externalEffect: true,
|
|
87491
|
-
requiredScopes: ["Mail.Send"]
|
|
87492
|
-
}
|
|
87493
|
-
]
|
|
87494
|
-
});
|
|
87495
|
-
|
|
87496
87999
|
// src/connectors/adapters/microsoft-excel-365.ts
|
|
87497
88000
|
var microsoftExcel365Connector = declarativeRestConnector({
|
|
87498
88001
|
kind: "microsoft-excel-365",
|
|
@@ -88366,348 +88869,6 @@ var microsoftTodoConnector = declarativeRestConnector({
|
|
|
88366
88869
|
]
|
|
88367
88870
|
});
|
|
88368
88871
|
|
|
88369
|
-
// src/connectors/adapters/microsoft-sharepoint.ts
|
|
88370
|
-
var microsoftSharepointConnector = declarativeRestConnector({
|
|
88371
|
-
kind: "microsoft-sharepoint",
|
|
88372
|
-
displayName: "Microsoft SharePoint",
|
|
88373
|
-
description: "Read SharePoint site metadata, list items, and files; create folders, lists, list items, and pages via Microsoft Graph.",
|
|
88374
|
-
auth: {
|
|
88375
|
-
kind: "oauth2",
|
|
88376
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
88377
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
88378
|
-
scopes: [
|
|
88379
|
-
"offline_access",
|
|
88380
|
-
"Sites.ReadWrite.All",
|
|
88381
|
-
"Files.ReadWrite.All"
|
|
88382
|
-
],
|
|
88383
|
-
clientIdEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_ID",
|
|
88384
|
-
clientSecretEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_SECRET"
|
|
88385
|
-
},
|
|
88386
|
-
category: "storage",
|
|
88387
|
-
defaultConsistencyModel: "authoritative",
|
|
88388
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
88389
|
-
test: { method: "GET", path: "/sites/root" },
|
|
88390
|
-
capabilities: [
|
|
88391
|
-
// ---------- Sites ----------
|
|
88392
|
-
{
|
|
88393
|
-
name: "find.site",
|
|
88394
|
-
class: "read",
|
|
88395
|
-
description: "Search SharePoint sites by display name or keyword (Graph $search).",
|
|
88396
|
-
parameters: {
|
|
88397
|
-
type: "object",
|
|
88398
|
-
properties: {
|
|
88399
|
-
search: { type: "string" },
|
|
88400
|
-
$top: { type: "integer" }
|
|
88401
|
-
},
|
|
88402
|
-
required: ["search"]
|
|
88403
|
-
},
|
|
88404
|
-
request: {
|
|
88405
|
-
method: "GET",
|
|
88406
|
-
path: "/sites",
|
|
88407
|
-
query: { search: "{search}", $top: "{$top}" }
|
|
88408
|
-
},
|
|
88409
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88410
|
-
},
|
|
88411
|
-
{
|
|
88412
|
-
name: "get.site.information",
|
|
88413
|
-
class: "read",
|
|
88414
|
-
description: "Read the metadata for a SharePoint site by site id.",
|
|
88415
|
-
parameters: {
|
|
88416
|
-
type: "object",
|
|
88417
|
-
properties: { siteId: { type: "string" } },
|
|
88418
|
-
required: ["siteId"]
|
|
88419
|
-
},
|
|
88420
|
-
request: { method: "GET", path: "/sites/{siteId}" },
|
|
88421
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88422
|
-
},
|
|
88423
|
-
// ---------- Folders / files ----------
|
|
88424
|
-
{
|
|
88425
|
-
name: "create.folder",
|
|
88426
|
-
class: "mutation",
|
|
88427
|
-
description: "Create a folder inside a site drive. Parent is identified by its drive item id (use the drive root id for top-level folders).",
|
|
88428
|
-
parameters: {
|
|
88429
|
-
type: "object",
|
|
88430
|
-
properties: {
|
|
88431
|
-
siteId: { type: "string" },
|
|
88432
|
-
parentItemId: { type: "string" },
|
|
88433
|
-
name: { type: "string" },
|
|
88434
|
-
conflictBehavior: { type: "string" }
|
|
88435
|
-
},
|
|
88436
|
-
required: ["siteId", "parentItemId", "name"]
|
|
88437
|
-
},
|
|
88438
|
-
request: {
|
|
88439
|
-
method: "POST",
|
|
88440
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}/children",
|
|
88441
|
-
body: {
|
|
88442
|
-
name: "{name}",
|
|
88443
|
-
folder: {},
|
|
88444
|
-
"@microsoft.graph.conflictBehavior": "{conflictBehavior}"
|
|
88445
|
-
}
|
|
88446
|
-
},
|
|
88447
|
-
cas: "native-idempotency",
|
|
88448
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88449
|
-
},
|
|
88450
|
-
{
|
|
88451
|
-
name: "get.folder.contents",
|
|
88452
|
-
class: "read",
|
|
88453
|
-
description: "List the children of a folder in a site drive.",
|
|
88454
|
-
parameters: {
|
|
88455
|
-
type: "object",
|
|
88456
|
-
properties: {
|
|
88457
|
-
siteId: { type: "string" },
|
|
88458
|
-
itemId: { type: "string" },
|
|
88459
|
-
$top: { type: "integer" },
|
|
88460
|
-
$select: { type: "string" }
|
|
88461
|
-
},
|
|
88462
|
-
required: ["siteId", "itemId"]
|
|
88463
|
-
},
|
|
88464
|
-
request: {
|
|
88465
|
-
method: "GET",
|
|
88466
|
-
path: "/sites/{siteId}/drive/items/{itemId}/children",
|
|
88467
|
-
query: { $top: "{$top}", $select: "{$select}" }
|
|
88468
|
-
},
|
|
88469
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88470
|
-
},
|
|
88471
|
-
{
|
|
88472
|
-
name: "find.file",
|
|
88473
|
-
class: "read",
|
|
88474
|
-
description: "Search drive items inside a site drive by name or content (Graph drive search).",
|
|
88475
|
-
parameters: {
|
|
88476
|
-
type: "object",
|
|
88477
|
-
properties: {
|
|
88478
|
-
siteId: { type: "string" },
|
|
88479
|
-
query: { type: "string" },
|
|
88480
|
-
$top: { type: "integer" }
|
|
88481
|
-
},
|
|
88482
|
-
required: ["siteId", "query"]
|
|
88483
|
-
},
|
|
88484
|
-
request: {
|
|
88485
|
-
method: "GET",
|
|
88486
|
-
path: "/sites/{siteId}/drive/root/search(q='{query}')",
|
|
88487
|
-
query: { $top: "{$top}" }
|
|
88488
|
-
},
|
|
88489
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88490
|
-
},
|
|
88491
|
-
{
|
|
88492
|
-
name: "upload.file",
|
|
88493
|
-
class: "mutation",
|
|
88494
|
-
description: "Upload (or replace) a small file at the given drive path. The body must be the JSON-encoded contents the agent provides as `content` (base64-encoded for binary payloads). For files larger than 4 MiB the caller should use the upload-session flow instead.",
|
|
88495
|
-
parameters: {
|
|
88496
|
-
type: "object",
|
|
88497
|
-
properties: {
|
|
88498
|
-
siteId: { type: "string" },
|
|
88499
|
-
parentItemId: { type: "string" },
|
|
88500
|
-
fileName: { type: "string" },
|
|
88501
|
-
content: { type: "string" },
|
|
88502
|
-
conflictBehavior: { type: "string" }
|
|
88503
|
-
},
|
|
88504
|
-
required: ["siteId", "parentItemId", "fileName", "content"]
|
|
88505
|
-
},
|
|
88506
|
-
request: {
|
|
88507
|
-
method: "PUT",
|
|
88508
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}:/{fileName}:/content",
|
|
88509
|
-
body: "{content}"
|
|
88510
|
-
},
|
|
88511
|
-
cas: "optimistic-read-verify",
|
|
88512
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88513
|
-
},
|
|
88514
|
-
{
|
|
88515
|
-
name: "copy.item",
|
|
88516
|
-
class: "mutation",
|
|
88517
|
-
description: "Copy a drive item into another drive. The destination is identified by a parentReference (driveId + id) and an optional new name.",
|
|
88518
|
-
parameters: {
|
|
88519
|
-
type: "object",
|
|
88520
|
-
properties: {
|
|
88521
|
-
siteId: { type: "string" },
|
|
88522
|
-
itemId: { type: "string" },
|
|
88523
|
-
parentReference: { type: "object" },
|
|
88524
|
-
name: { type: "string" }
|
|
88525
|
-
},
|
|
88526
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88527
|
-
},
|
|
88528
|
-
request: {
|
|
88529
|
-
method: "POST",
|
|
88530
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88531
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88532
|
-
},
|
|
88533
|
-
cas: "native-idempotency",
|
|
88534
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88535
|
-
},
|
|
88536
|
-
{
|
|
88537
|
-
name: "copy.item.within.site",
|
|
88538
|
-
class: "mutation",
|
|
88539
|
-
description: "Copy a drive item to another folder inside the same site drive. The destination parent is identified by the target folder id.",
|
|
88540
|
-
parameters: {
|
|
88541
|
-
type: "object",
|
|
88542
|
-
properties: {
|
|
88543
|
-
siteId: { type: "string" },
|
|
88544
|
-
itemId: { type: "string" },
|
|
88545
|
-
targetParentId: { type: "string" },
|
|
88546
|
-
name: { type: "string" }
|
|
88547
|
-
},
|
|
88548
|
-
required: ["siteId", "itemId", "targetParentId"]
|
|
88549
|
-
},
|
|
88550
|
-
request: {
|
|
88551
|
-
method: "POST",
|
|
88552
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88553
|
-
body: { parentReference: { id: "{targetParentId}" }, name: "{name}" }
|
|
88554
|
-
},
|
|
88555
|
-
cas: "native-idempotency",
|
|
88556
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88557
|
-
},
|
|
88558
|
-
{
|
|
88559
|
-
name: "move.file",
|
|
88560
|
-
class: "mutation",
|
|
88561
|
-
description: "Move (re-parent or rename) a drive item by patching its parentReference and/or name.",
|
|
88562
|
-
parameters: {
|
|
88563
|
-
type: "object",
|
|
88564
|
-
properties: {
|
|
88565
|
-
siteId: { type: "string" },
|
|
88566
|
-
itemId: { type: "string" },
|
|
88567
|
-
parentReference: { type: "object" },
|
|
88568
|
-
name: { type: "string" }
|
|
88569
|
-
},
|
|
88570
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88571
|
-
},
|
|
88572
|
-
request: {
|
|
88573
|
-
method: "PATCH",
|
|
88574
|
-
path: "/sites/{siteId}/drive/items/{itemId}",
|
|
88575
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88576
|
-
},
|
|
88577
|
-
cas: "etag-if-match",
|
|
88578
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88579
|
-
},
|
|
88580
|
-
// ---------- Lists & list items ----------
|
|
88581
|
-
{
|
|
88582
|
-
name: "create.list",
|
|
88583
|
-
class: "mutation",
|
|
88584
|
-
description: "Create a SharePoint list on the site. `displayName` is required; `columns` and `list.template` are optional.",
|
|
88585
|
-
parameters: {
|
|
88586
|
-
type: "object",
|
|
88587
|
-
properties: {
|
|
88588
|
-
siteId: { type: "string" },
|
|
88589
|
-
displayName: { type: "string" },
|
|
88590
|
-
columns: { type: "array", items: { type: "object" } },
|
|
88591
|
-
list: { type: "object" }
|
|
88592
|
-
},
|
|
88593
|
-
required: ["siteId", "displayName"]
|
|
88594
|
-
},
|
|
88595
|
-
request: {
|
|
88596
|
-
method: "POST",
|
|
88597
|
-
path: "/sites/{siteId}/lists",
|
|
88598
|
-
body: { displayName: "{displayName}", columns: "{columns}", list: "{list}" }
|
|
88599
|
-
},
|
|
88600
|
-
cas: "native-idempotency",
|
|
88601
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88602
|
-
},
|
|
88603
|
-
{
|
|
88604
|
-
name: "create.list.item",
|
|
88605
|
-
class: "mutation",
|
|
88606
|
-
description: "Create a new list item. `fields` is the column -> value map.",
|
|
88607
|
-
parameters: {
|
|
88608
|
-
type: "object",
|
|
88609
|
-
properties: {
|
|
88610
|
-
siteId: { type: "string" },
|
|
88611
|
-
listId: { type: "string" },
|
|
88612
|
-
fields: { type: "object" }
|
|
88613
|
-
},
|
|
88614
|
-
required: ["siteId", "listId", "fields"]
|
|
88615
|
-
},
|
|
88616
|
-
request: {
|
|
88617
|
-
method: "POST",
|
|
88618
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88619
|
-
body: { fields: "{fields}" }
|
|
88620
|
-
},
|
|
88621
|
-
cas: "native-idempotency",
|
|
88622
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88623
|
-
},
|
|
88624
|
-
{
|
|
88625
|
-
name: "update.list.item",
|
|
88626
|
-
class: "mutation",
|
|
88627
|
-
description: "Patch the fields on an existing list item.",
|
|
88628
|
-
parameters: {
|
|
88629
|
-
type: "object",
|
|
88630
|
-
properties: {
|
|
88631
|
-
siteId: { type: "string" },
|
|
88632
|
-
listId: { type: "string" },
|
|
88633
|
-
itemId: { type: "string" },
|
|
88634
|
-
fields: { type: "object" }
|
|
88635
|
-
},
|
|
88636
|
-
required: ["siteId", "listId", "itemId", "fields"]
|
|
88637
|
-
},
|
|
88638
|
-
request: {
|
|
88639
|
-
method: "PATCH",
|
|
88640
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}/fields",
|
|
88641
|
-
body: "{fields}"
|
|
88642
|
-
},
|
|
88643
|
-
cas: "etag-if-match",
|
|
88644
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88645
|
-
},
|
|
88646
|
-
{
|
|
88647
|
-
name: "delete.list.item",
|
|
88648
|
-
class: "mutation",
|
|
88649
|
-
description: "Delete a list item by id.",
|
|
88650
|
-
parameters: {
|
|
88651
|
-
type: "object",
|
|
88652
|
-
properties: {
|
|
88653
|
-
siteId: { type: "string" },
|
|
88654
|
-
listId: { type: "string" },
|
|
88655
|
-
itemId: { type: "string" }
|
|
88656
|
-
},
|
|
88657
|
-
required: ["siteId", "listId", "itemId"]
|
|
88658
|
-
},
|
|
88659
|
-
request: {
|
|
88660
|
-
method: "DELETE",
|
|
88661
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}"
|
|
88662
|
-
},
|
|
88663
|
-
cas: "native-idempotency",
|
|
88664
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88665
|
-
},
|
|
88666
|
-
{
|
|
88667
|
-
name: "find.list.item",
|
|
88668
|
-
class: "read",
|
|
88669
|
-
description: "List items in a SharePoint list, optionally filtered with $filter / $expand=fields($select=...).",
|
|
88670
|
-
parameters: {
|
|
88671
|
-
type: "object",
|
|
88672
|
-
properties: {
|
|
88673
|
-
siteId: { type: "string" },
|
|
88674
|
-
listId: { type: "string" },
|
|
88675
|
-
$filter: { type: "string" },
|
|
88676
|
-
$expand: { type: "string" },
|
|
88677
|
-
$top: { type: "integer" }
|
|
88678
|
-
},
|
|
88679
|
-
required: ["siteId", "listId"]
|
|
88680
|
-
},
|
|
88681
|
-
request: {
|
|
88682
|
-
method: "GET",
|
|
88683
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88684
|
-
query: { $filter: "{$filter}", $expand: "{$expand}", $top: "{$top}" }
|
|
88685
|
-
},
|
|
88686
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88687
|
-
},
|
|
88688
|
-
// ---------- Pages ----------
|
|
88689
|
-
{
|
|
88690
|
-
name: "publish.page",
|
|
88691
|
-
class: "mutation",
|
|
88692
|
-
description: "Publish a SharePoint site page by page id.",
|
|
88693
|
-
parameters: {
|
|
88694
|
-
type: "object",
|
|
88695
|
-
properties: {
|
|
88696
|
-
siteId: { type: "string" },
|
|
88697
|
-
pageId: { type: "string" }
|
|
88698
|
-
},
|
|
88699
|
-
required: ["siteId", "pageId"]
|
|
88700
|
-
},
|
|
88701
|
-
request: {
|
|
88702
|
-
method: "POST",
|
|
88703
|
-
path: "/sites/{siteId}/pages/{pageId}/microsoft.graph.sitePage/publish"
|
|
88704
|
-
},
|
|
88705
|
-
cas: "native-idempotency",
|
|
88706
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88707
|
-
}
|
|
88708
|
-
]
|
|
88709
|
-
});
|
|
88710
|
-
|
|
88711
88872
|
// src/connectors/adapters/millionverifier.ts
|
|
88712
88873
|
var millionverifierConnector = declarativeRestConnector({
|
|
88713
88874
|
kind: "millionverifier",
|
|
@@ -92609,82 +92770,6 @@ var mindStudioConnector = declarativeRestConnector({
|
|
|
92609
92770
|
]
|
|
92610
92771
|
});
|
|
92611
92772
|
|
|
92612
|
-
// src/connectors/adapters/microsoft-onedrive.ts
|
|
92613
|
-
var microsoftOnedriveConnector = declarativeRestConnector({
|
|
92614
|
-
kind: "microsoft-onedrive",
|
|
92615
|
-
displayName: "Microsoft OneDrive",
|
|
92616
|
-
description: "Upload, download, list files and folders in Microsoft OneDrive.",
|
|
92617
|
-
auth: {
|
|
92618
|
-
kind: "oauth2",
|
|
92619
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
92620
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
92621
|
-
scopes: ["Files.ReadWrite"],
|
|
92622
|
-
clientIdEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_ID",
|
|
92623
|
-
clientSecretEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_SECRET"
|
|
92624
|
-
},
|
|
92625
|
-
category: "storage",
|
|
92626
|
-
defaultConsistencyModel: "authoritative",
|
|
92627
|
-
baseUrl: "https://graph.microsoft.com/v1.0/me/drive",
|
|
92628
|
-
test: { method: "GET", path: "/root" },
|
|
92629
|
-
capabilities: [
|
|
92630
|
-
{
|
|
92631
|
-
name: "files.list",
|
|
92632
|
-
class: "read",
|
|
92633
|
-
description: "List files in OneDrive.",
|
|
92634
|
-
parameters: {
|
|
92635
|
-
type: "object",
|
|
92636
|
-
properties: {
|
|
92637
|
-
folderId: { type: "string", description: "Folder ID to list files from (optional, defaults to root)" }
|
|
92638
|
-
},
|
|
92639
|
-
required: []
|
|
92640
|
-
},
|
|
92641
|
-
request: { method: "GET", path: "/items/{folderId}/children", query: { $select: "id,name,size,webUrl,folder,file" } }
|
|
92642
|
-
},
|
|
92643
|
-
{
|
|
92644
|
-
name: "folders.list",
|
|
92645
|
-
class: "read",
|
|
92646
|
-
description: "List folders in OneDrive.",
|
|
92647
|
-
parameters: {
|
|
92648
|
-
type: "object",
|
|
92649
|
-
properties: {
|
|
92650
|
-
parentId: { type: "string", description: "Parent folder ID (optional, defaults to root)" }
|
|
92651
|
-
},
|
|
92652
|
-
required: []
|
|
92653
|
-
},
|
|
92654
|
-
request: { method: "GET", path: "/items/{parentId}/children", query: { $filter: "folder ne null", $select: "id,name,webUrl" } }
|
|
92655
|
-
},
|
|
92656
|
-
{
|
|
92657
|
-
name: "files.download",
|
|
92658
|
-
class: "read",
|
|
92659
|
-
description: "Download a file from OneDrive.",
|
|
92660
|
-
parameters: {
|
|
92661
|
-
type: "object",
|
|
92662
|
-
properties: {
|
|
92663
|
-
fileId: { type: "string" }
|
|
92664
|
-
},
|
|
92665
|
-
required: ["fileId"]
|
|
92666
|
-
},
|
|
92667
|
-
request: { method: "GET", path: "/items/{fileId}/content" }
|
|
92668
|
-
},
|
|
92669
|
-
{
|
|
92670
|
-
name: "files.upload",
|
|
92671
|
-
class: "mutation",
|
|
92672
|
-
description: "Upload a file to OneDrive.",
|
|
92673
|
-
parameters: {
|
|
92674
|
-
type: "object",
|
|
92675
|
-
properties: {
|
|
92676
|
-
folderId: { type: "string", description: "Destination folder ID (optional, defaults to root)" },
|
|
92677
|
-
fileName: { type: "string", description: "Name of the file to upload" },
|
|
92678
|
-
fileContent: { type: "string", description: "File content (base64-encoded or raw)" }
|
|
92679
|
-
},
|
|
92680
|
-
required: ["fileName", "fileContent"]
|
|
92681
|
-
},
|
|
92682
|
-
request: { method: "PUT", path: "/items/{folderId}:/{fileName}:/content", body: "{fileContent}" },
|
|
92683
|
-
cas: "native-idempotency"
|
|
92684
|
-
}
|
|
92685
|
-
]
|
|
92686
|
-
});
|
|
92687
|
-
|
|
92688
92773
|
// src/connectors/adapters/mongodb.ts
|
|
92689
92774
|
var mongodbConnector = declarativeRestConnector({
|
|
92690
92775
|
kind: "mongodb",
|
|
@@ -93846,7 +93931,9 @@ var nocodbConnector = declarativeRestConnector({
|
|
|
93846
93931
|
});
|
|
93847
93932
|
|
|
93848
93933
|
// src/connectors/adapters/notion.ts
|
|
93849
|
-
var
|
|
93934
|
+
var TOKEN_URL18 = "https://api.notion.com/v1/oauth/token";
|
|
93935
|
+
var NOTION_VERSION = "2022-06-28";
|
|
93936
|
+
var NOTION_SPEC = {
|
|
93850
93937
|
kind: "notion",
|
|
93851
93938
|
displayName: "Notion",
|
|
93852
93939
|
description: "Query and manipulate Notion databases, pages, and blocks.",
|
|
@@ -93854,13 +93941,21 @@ var notionConnector = declarativeRestConnector({
|
|
|
93854
93941
|
kind: "oauth2",
|
|
93855
93942
|
authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
|
|
93856
93943
|
tokenUrl: "https://api.notion.com/v1/oauth/token",
|
|
93857
|
-
scopes
|
|
93944
|
+
// Notion does not use OAuth scopes — the workspace owner picks which
|
|
93945
|
+
// pages/databases the integration sees during install. We declare an
|
|
93946
|
+
// empty scope list so the consent screen renders cleanly.
|
|
93947
|
+
scopes: [],
|
|
93858
93948
|
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
93859
|
-
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET"
|
|
93949
|
+
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
93950
|
+
extraAuthParams: { owner: "user" }
|
|
93860
93951
|
},
|
|
93861
93952
|
category: "doc",
|
|
93862
93953
|
defaultConsistencyModel: "authoritative",
|
|
93863
93954
|
baseUrl: "https://api.notion.com/v1",
|
|
93955
|
+
// Notion rejects any request without a Notion-Version header (400
|
|
93956
|
+
// invalid_request). The declarative executor merges defaultHeaders into
|
|
93957
|
+
// every read/mutation, so the whole surface carries it.
|
|
93958
|
+
defaultHeaders: { "Notion-Version": NOTION_VERSION },
|
|
93864
93959
|
test: { method: "GET", path: "/users/me" },
|
|
93865
93960
|
capabilities: [
|
|
93866
93961
|
{
|
|
@@ -94091,9 +94186,168 @@ var notionConnector = declarativeRestConnector({
|
|
|
94091
94186
|
},
|
|
94092
94187
|
cas: "native-idempotency",
|
|
94093
94188
|
externalEffect: true
|
|
94189
|
+
},
|
|
94190
|
+
{
|
|
94191
|
+
name: "databases.create",
|
|
94192
|
+
class: "mutation",
|
|
94193
|
+
description: "Create a new Notion database underneath a parent page.",
|
|
94194
|
+
parameters: {
|
|
94195
|
+
type: "object",
|
|
94196
|
+
properties: {
|
|
94197
|
+
parentPageId: { type: "string", description: "Parent page id under which to create the database." },
|
|
94198
|
+
title: {
|
|
94199
|
+
type: "array",
|
|
94200
|
+
description: "Notion rich_text array used as the database title."
|
|
94201
|
+
},
|
|
94202
|
+
properties: {
|
|
94203
|
+
type: "object",
|
|
94204
|
+
description: "Schema map \u2014 property name \u2192 Notion property schema."
|
|
94205
|
+
}
|
|
94206
|
+
},
|
|
94207
|
+
required: ["parentPageId", "title", "properties"]
|
|
94208
|
+
},
|
|
94209
|
+
request: {
|
|
94210
|
+
method: "POST",
|
|
94211
|
+
path: "/databases",
|
|
94212
|
+
body: {
|
|
94213
|
+
parent: { type: "page_id", page_id: "{parentPageId}" },
|
|
94214
|
+
title: "{title}",
|
|
94215
|
+
properties: "{properties}"
|
|
94216
|
+
}
|
|
94217
|
+
},
|
|
94218
|
+
cas: "native-idempotency",
|
|
94219
|
+
externalEffect: true
|
|
94220
|
+
},
|
|
94221
|
+
{
|
|
94222
|
+
name: "databases.update",
|
|
94223
|
+
class: "mutation",
|
|
94224
|
+
description: "Update a database title and/or schema.",
|
|
94225
|
+
parameters: {
|
|
94226
|
+
type: "object",
|
|
94227
|
+
properties: {
|
|
94228
|
+
databaseId: { type: "string" },
|
|
94229
|
+
title: { type: "array", description: "Optional new rich_text title." },
|
|
94230
|
+
properties: { type: "object", description: "Optional partial schema update." }
|
|
94231
|
+
},
|
|
94232
|
+
required: ["databaseId"]
|
|
94233
|
+
},
|
|
94234
|
+
request: {
|
|
94235
|
+
method: "PATCH",
|
|
94236
|
+
path: "/databases/{databaseId}",
|
|
94237
|
+
body: { title: "{title}", properties: "{properties}" }
|
|
94238
|
+
},
|
|
94239
|
+
cas: "native-idempotency",
|
|
94240
|
+
externalEffect: true
|
|
94094
94241
|
}
|
|
94095
94242
|
]
|
|
94096
|
-
}
|
|
94243
|
+
};
|
|
94244
|
+
async function databasesUpdate(inv) {
|
|
94245
|
+
const { title, properties } = inv.args;
|
|
94246
|
+
const body = {};
|
|
94247
|
+
if (title !== void 0) body.title = "{title}";
|
|
94248
|
+
if (properties !== void 0) body.properties = "{properties}";
|
|
94249
|
+
const response = await executeRestRequest(
|
|
94250
|
+
NOTION_SPEC,
|
|
94251
|
+
{ method: "PATCH", path: "/databases/{databaseId}", body },
|
|
94252
|
+
inv
|
|
94253
|
+
);
|
|
94254
|
+
return {
|
|
94255
|
+
status: "committed",
|
|
94256
|
+
data: response.data,
|
|
94257
|
+
etagAfter: response.etag,
|
|
94258
|
+
committedAt: Date.now(),
|
|
94259
|
+
idempotentReplay: false
|
|
94260
|
+
};
|
|
94261
|
+
}
|
|
94262
|
+
function withNotionOverrides(base) {
|
|
94263
|
+
return {
|
|
94264
|
+
...base,
|
|
94265
|
+
async executeMutation(inv) {
|
|
94266
|
+
if (inv.capabilityName === "databases.update") return databasesUpdate(inv);
|
|
94267
|
+
return base.executeMutation(inv);
|
|
94268
|
+
}
|
|
94269
|
+
};
|
|
94270
|
+
}
|
|
94271
|
+
var notionConnector = withNotionOverrides(declarativeRestConnector(NOTION_SPEC));
|
|
94272
|
+
function notion(opts) {
|
|
94273
|
+
const { clientId, clientSecret } = opts;
|
|
94274
|
+
return {
|
|
94275
|
+
...withNotionOverrides(declarativeRestConnector(NOTION_SPEC)),
|
|
94276
|
+
/**
|
|
94277
|
+
* Notion's token endpoint follows RFC 6749 with one twist — it REQUIRES
|
|
94278
|
+
* HTTP Basic auth (client_id:client_secret) and does NOT accept the client
|
|
94279
|
+
* credentials in the form body, so we POST inline rather than via the
|
|
94280
|
+
* generic `exchangeAuthorizationCode` helper. The workspace_id/bot_id come
|
|
94281
|
+
* back in the response and we stash them in `metadata` so the agent can
|
|
94282
|
+
* address resources by workspace where useful.
|
|
94283
|
+
*/
|
|
94284
|
+
async exchangeOAuth(input) {
|
|
94285
|
+
if (!clientId || !clientSecret) {
|
|
94286
|
+
throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
|
|
94287
|
+
}
|
|
94288
|
+
const body = new URLSearchParams({
|
|
94289
|
+
grant_type: "authorization_code",
|
|
94290
|
+
code: input.code,
|
|
94291
|
+
redirect_uri: input.redirectUri,
|
|
94292
|
+
code_verifier: input.codeVerifier
|
|
94293
|
+
});
|
|
94294
|
+
const res = await fetch(TOKEN_URL18, {
|
|
94295
|
+
method: "POST",
|
|
94296
|
+
headers: {
|
|
94297
|
+
authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
|
|
94298
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
94299
|
+
accept: "application/json",
|
|
94300
|
+
"Notion-Version": NOTION_VERSION
|
|
94301
|
+
},
|
|
94302
|
+
body,
|
|
94303
|
+
signal: AbortSignal.timeout(15e3)
|
|
94304
|
+
});
|
|
94305
|
+
if (!res.ok) {
|
|
94306
|
+
const text = await res.text().catch(() => "");
|
|
94307
|
+
throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
|
|
94308
|
+
}
|
|
94309
|
+
const json = await res.json();
|
|
94310
|
+
return {
|
|
94311
|
+
credentials: {
|
|
94312
|
+
kind: "oauth2",
|
|
94313
|
+
accessToken: json.access_token,
|
|
94314
|
+
refreshToken: json.refresh_token
|
|
94315
|
+
},
|
|
94316
|
+
scopes: [],
|
|
94317
|
+
metadata: {
|
|
94318
|
+
botId: json.bot_id,
|
|
94319
|
+
workspaceId: json.workspace_id,
|
|
94320
|
+
workspaceName: json.workspace_name,
|
|
94321
|
+
// Operator picks the database in a follow-up step; default empty.
|
|
94322
|
+
databaseId: ""
|
|
94323
|
+
}
|
|
94324
|
+
};
|
|
94325
|
+
},
|
|
94326
|
+
/** Notion's standard tokens don't expire and don't ship a refresh_token.
|
|
94327
|
+
* If we have neither expiresAt nor refreshToken, treat the existing
|
|
94328
|
+
* access token as durable and return it unchanged. */
|
|
94329
|
+
async refreshToken(creds) {
|
|
94330
|
+
if (creds.kind !== "oauth2" || !creds.refreshToken) {
|
|
94331
|
+
if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
|
|
94332
|
+
return creds;
|
|
94333
|
+
}
|
|
94334
|
+
throw new Error("notion.refreshToken: missing refresh token");
|
|
94335
|
+
}
|
|
94336
|
+
const refreshed = await refreshAccessToken({
|
|
94337
|
+
tokenUrl: TOKEN_URL18,
|
|
94338
|
+
clientId,
|
|
94339
|
+
clientSecret,
|
|
94340
|
+
refreshToken: creds.refreshToken
|
|
94341
|
+
});
|
|
94342
|
+
return {
|
|
94343
|
+
kind: "oauth2",
|
|
94344
|
+
accessToken: refreshed.accessToken,
|
|
94345
|
+
refreshToken: refreshed.refreshToken ?? creds.refreshToken,
|
|
94346
|
+
expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
|
|
94347
|
+
};
|
|
94348
|
+
}
|
|
94349
|
+
};
|
|
94350
|
+
}
|
|
94097
94351
|
|
|
94098
94352
|
// src/connectors/adapters/ntfy.ts
|
|
94099
94353
|
var ntfyConnector = declarativeRestConnector({
|
|
@@ -111284,7 +111538,7 @@ var twinLabsConnector = declarativeRestConnector({
|
|
|
111284
111538
|
});
|
|
111285
111539
|
|
|
111286
111540
|
// src/connectors/adapters/twitter.ts
|
|
111287
|
-
var
|
|
111541
|
+
var AUTH_URL18 = "https://twitter.com/i/oauth2/authorize";
|
|
111288
111542
|
var TOKEN_URL19 = "https://api.twitter.com/2/oauth2/token";
|
|
111289
111543
|
var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "like.write", "offline.access"];
|
|
111290
111544
|
var TWITTER_SPEC = {
|
|
@@ -111297,7 +111551,7 @@ var TWITTER_SPEC = {
|
|
|
111297
111551
|
options: [
|
|
111298
111552
|
{
|
|
111299
111553
|
kind: "oauth2",
|
|
111300
|
-
authorizationUrl:
|
|
111554
|
+
authorizationUrl: AUTH_URL18,
|
|
111301
111555
|
tokenUrl: TOKEN_URL19,
|
|
111302
111556
|
scopes: SCOPES14,
|
|
111303
111557
|
clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
|
|
@@ -118456,7 +118710,6 @@ export {
|
|
|
118456
118710
|
microsoftCalendar,
|
|
118457
118711
|
hubspot,
|
|
118458
118712
|
slack,
|
|
118459
|
-
notionDatabase,
|
|
118460
118713
|
docuseal,
|
|
118461
118714
|
twilioSmsConnector,
|
|
118462
118715
|
phonyConnector,
|
|
@@ -118693,6 +118946,8 @@ export {
|
|
|
118693
118946
|
ghostcmsConnector,
|
|
118694
118947
|
gistlyConnector,
|
|
118695
118948
|
googleSearchConsoleConnector,
|
|
118949
|
+
googleAnalyticsConnector,
|
|
118950
|
+
googleMeetConnector,
|
|
118696
118951
|
youtubeDataConnector,
|
|
118697
118952
|
googleCloudStorageConnector,
|
|
118698
118953
|
googleBigqueryConnector,
|
|
@@ -118770,12 +119025,9 @@ export {
|
|
|
118770
119025
|
microsoftDynamics365BusinessCentralConnector,
|
|
118771
119026
|
microsoft365PlannerConnector,
|
|
118772
119027
|
microsoftPowerBiConnector,
|
|
118773
|
-
microsoftOutlookCalendarConnector,
|
|
118774
119028
|
microsoftOnenoteConnector,
|
|
118775
|
-
microsoftOutlookConnector,
|
|
118776
119029
|
microsoftExcel365Connector,
|
|
118777
119030
|
microsoftTodoConnector,
|
|
118778
|
-
microsoftSharepointConnector,
|
|
118779
119031
|
millionverifierConnector,
|
|
118780
119032
|
mindeeConnector,
|
|
118781
119033
|
mixmaxConnector,
|
|
@@ -118806,12 +119058,12 @@ export {
|
|
|
118806
119058
|
mollieConnector,
|
|
118807
119059
|
metabaseConnector,
|
|
118808
119060
|
mindStudioConnector,
|
|
118809
|
-
microsoftOnedriveConnector,
|
|
118810
119061
|
mongodbConnector,
|
|
118811
119062
|
niftyConnector,
|
|
118812
119063
|
ninjapipeConnector,
|
|
118813
119064
|
nocodbConnector,
|
|
118814
119065
|
notionConnector,
|
|
119066
|
+
notion,
|
|
118815
119067
|
ntfyConnector,
|
|
118816
119068
|
odooConnector,
|
|
118817
119069
|
omniCoConnector,
|
|
@@ -118940,4 +119192,4 @@ export {
|
|
|
118940
119192
|
pipedreamConnector,
|
|
118941
119193
|
adapters_exports
|
|
118942
119194
|
};
|
|
118943
|
-
//# sourceMappingURL=chunk-
|
|
119195
|
+
//# sourceMappingURL=chunk-4TI3WXAD.js.map
|